1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Python Wrapper
3 * Title: cmsismodule.c
4 * Description: C code for the CMSIS-DSP Python wrapper
5 *
6 * $Date: 27 April 2021
7 * $Revision: VV1.0
8 *
9 * Target Processor: Cortex-M cores
10 * -------------------------------------------------------------------- */
11 /*
12 * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13 *
14 * SPDX-License-Identifier: Apache-2.0
15 *
16 * Licensed under the Apache License, Version 2.0 (the License); you may
17 * not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28 #ifndef CMSISMODULE_H
29 #define CMSISMODULE_H
30 #define NPY_NO_DEPRECATED_API NPY_1_23_API_VERSION
31
32 #include <numpy/numpyconfig.h>
33
34 // Check it is built with right version
35 // (should be backward compatible down to 1.23.5)
36 // https://github.com/numpy/numpy/blob/main/numpy/_core/include/numpy/numpyconfig.h
37 #if (NPY_API_VERSION != NPY_2_0_API_VERSION )
38 #error("Error building with wrong NumPy API version")
39 #endif
40
41 #ifdef WIN
42 #pragma warning( disable : 4013 )
43 #pragma warning( disable : 4244 )
44 #endif
45
46 #include <Python.h>
47
48 #define CAT1(A,B) A##B
49 #define CAT(A,B) CAT1(A,B)
50
51
52 #include "arm_math.h"
53
54
55 #include <numpy/arrayobject.h>
56 #include <numpy/ndarraytypes.h>
57
58 #if PY_MAJOR_VERSION >= 3
59 #define IS_PY3K
60 #endif
61
62 struct module_state {
63 PyObject *error;
64 };
65
66 #if PY_MAJOR_VERSION >= 3
67 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
68 #else
69 #define GETSTATE(m) (&_state)
70 static struct module_state _state;
71 #endif
72
73 static PyObject *
error_out(PyObject * m)74 error_out(PyObject *m) {
75 struct module_state *st = GETSTATE(m);
76 PyErr_SetString(st->error, "something bad happened");
77 return NULL;
78 }
79
80 #define DSPType(name,thenewfunc,deallocfunc,initfunc,methods)\
81 static PyTypeObject dsp_##name##Type = { \
82 PyVarObject_HEAD_INIT(NULL, 0) \
83 .tp_name=MODNAME"." #name, \
84 .tp_basicsize = sizeof(dsp_##name##Object), \
85 .tp_itemsize = 0, \
86 .tp_dealloc = (destructor)deallocfunc, \
87 .tp_flags = Py_TPFLAGS_DEFAULT, \
88 .tp_doc = #name, \
89 .tp_init = (initproc)initfunc, \
90 .tp_new = (newfunc)thenewfunc, \
91 .tp_methods = methods \
92 };
93
94
95 #define MEMCPY(DST,SRC,NB,FORMAT) \
96 for(memCpyIndex = 0; memCpyIndex < (NB) ; memCpyIndex++)\
97 { \
98 (DST)[memCpyIndex] = (FORMAT)(SRC)[memCpyIndex]; \
99 }
100
101 #define GETFIELD(NAME,FIELD,FORMAT) \
102 static PyObject * \
103 Method_##NAME##_##FIELD(dsp_##NAME##Object *self, PyObject *ignored)\
104 { \
105 return(Py_BuildValue(FORMAT,self->instance->FIELD)); \
106 }
107
108 #define GETFIELDARRAY(NAME,FIELD,FORMAT) \
109 static PyObject * \
110 Method_##NAME##_##FIELD(dsp_##NAME##Object *self, PyObject *ignored)\
111 { \
112 return(specific_##NAME##_##FIELD(self->instance)); \
113 }
114
115 #define INITARRAYFIELD(FIELD,FORMAT,SRCFORMAT,DSTFORMAT) \
116 if (FIELD) \
117 { \
118 PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \
119 PyArrayObject *FIELD##c = (PyArrayObject *)PyArray_FromAny(FIELD,desct,\
120 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \
121 NULL); \
122 if (FIELD##c) \
123 { \
124 uint32_t memCpyIndex; \
125 SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(FIELD##c); \
126 uint32_t n = PyArray_SIZE(FIELD##c); \
127 self->instance->FIELD =PyMem_Malloc(sizeof(DSTFORMAT)*n); \
128 MEMCPY((DSTFORMAT*)self->instance->FIELD ,f,n,DSTFORMAT); \
129 Py_DECREF(FIELD##c); \
130 } \
131 }
132 #define GETCARRAY(PYVAR,CVAR,FORMAT,SRCFORMAT,DSTFORMAT) \
133 if (PYVAR) \
134 { \
135 PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \
136 PyArrayObject *PYVAR##c = (PyArrayObject *)PyArray_FromAny(PYVAR,desct,\
137 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \
138 NULL); \
139 if (PYVAR##c) \
140 { \
141 uint32_t memCpyIndex; \
142 SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(PYVAR##c); \
143 uint32_t n = PyArray_SIZE(PYVAR##c); \
144 CVAR =PyMem_Malloc(sizeof(DSTFORMAT)*n); \
145 MEMCPY(CVAR ,f,n,DSTFORMAT); \
146 Py_DECREF(PYVAR##c); \
147 } \
148 }
149
150 #define GETARGUMENT(FIELD,FORMAT,SRCFORMAT,DSTFORMAT) \
151 uint32_t arraySize##FIELD=0; \
152 if (FIELD) \
153 { \
154 PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \
155 PyArrayObject *FIELD##c = (PyArrayObject *)PyArray_FromAny(FIELD,desct, \
156 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \
157 NULL); \
158 if (FIELD##c) \
159 { \
160 uint32_t memCpyIndex; \
161 SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(FIELD##c); \
162 arraySize##FIELD = PyArray_SIZE(FIELD##c); \
163 FIELD##_converted =PyMem_Malloc(sizeof(DSTFORMAT)*arraySize##FIELD);\
164 MEMCPY(FIELD##_converted ,f,arraySize##FIELD,DSTFORMAT); \
165 Py_DECREF(FIELD##c); \
166 } \
167 }
168
169 #define FREEARGUMENT(FIELD) \
170 PyMem_Free(FIELD)
171
172 #ifdef IS_PY3K
173 #define ADDTYPE(name) \
174 if (PyType_Ready(&dsp_##name##Type) < 0) \
175 return; \
176 \
177 Py_INCREF(&dsp_##name##Type); \
178 PyModule_AddObject(module, #name, (PyObject *)&dsp_##name##Type);
179 #else
180 #define ADDTYPE(name) \
181 if (PyType_Ready(&dsp_##name##Type) < 0) \
182 return; \
183 \
184 Py_INCREF(&dsp_##name##Type); \
185 PyModule_AddObject(module, #name, (PyObject *)&dsp_##name##Type);
186 #endif
187
capsule_cleanup(PyObject * capsule)188 void capsule_cleanup(PyObject *capsule) {
189 void *memory = PyCapsule_GetPointer(capsule, "cmsisdsp capsule");
190 PyMem_Free(memory);
191 }
192
193 #define FLOATARRAY2(OBJ,NB1,NB2,DATA) \
194 npy_intp dims##OBJ[2]; \
195 dims##OBJ[0]=NB1; \
196 dims##OBJ[1]=NB2; \
197 const int ND##OBJ=2; \
198 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_FLOAT, DATA);\
199 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
200 PyArray_SetBaseObject(OBJ, capsule##OBJ);
201
202 #define FLOATARRAY1(OBJ,NB1,DATA) \
203 npy_intp dims##OBJ[1]; \
204 dims##OBJ[0]=NB1; \
205 const int ND##OBJ=1; \
206 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_FLOAT, DATA);\
207 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
208 PyArray_SetBaseObject(OBJ, capsule##OBJ);
209
210 #define FLOAT64ARRAY1(OBJ,NB1,DATA) \
211 npy_intp dims##OBJ[1]; \
212 dims##OBJ[0]=NB1; \
213 const int ND##OBJ=1; \
214 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_DOUBLE, DATA);\
215 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
216 PyArray_SetBaseObject(OBJ, capsule##OBJ);
217
218 #define UINT32ARRAY1(OBJ,NB1,DATA) \
219 npy_intp dims##OBJ[1]; \
220 dims##OBJ[0]=NB1; \
221 const int ND##OBJ=1; \
222 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_UINT32, DATA);\
223 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
224 PyArray_SetBaseObject(OBJ, capsule##OBJ);
225
226 #define INT32ARRAY1(OBJ,NB1,DATA) \
227 npy_intp dims##OBJ[1]; \
228 dims##OBJ[0]=NB1; \
229 const int ND##OBJ=1; \
230 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_INT32, DATA);\
231 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
232 PyArray_SetBaseObject(OBJ, capsule##OBJ);
233
234 #define INT16ARRAY1(OBJ,NB1,DATA) \
235 npy_intp dims##OBJ[1]; \
236 dims##OBJ[0]=NB1; \
237 const int ND##OBJ=1; \
238 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_INT16, DATA);\
239 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
240 PyArray_SetBaseObject(OBJ, capsule##OBJ);
241
242 #define INT8ARRAY1(OBJ,NB1,DATA) \
243 npy_intp dims##OBJ[1]; \
244 dims##OBJ[0]=NB1; \
245 const int ND##OBJ=1; \
246 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPY_BYTE, DATA);\
247 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
248 PyArray_SetBaseObject(OBJ, capsule##OBJ);
249
250 #define TYP_ARRAY1(OBJ,NB1,DATA,NPYTYPE) \
251 npy_intp dims##OBJ[1]; \
252 dims##OBJ[0]=NB1; \
253 const int ND##OBJ=1; \
254 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND##OBJ, dims##OBJ, NPYTYPE, DATA);\
255 PyObject *capsule##OBJ = PyCapsule_New(DATA, "cmsisdsp capsule",capsule_cleanup); \
256 PyArray_SetBaseObject(OBJ, capsule##OBJ);
257
258 #define MATRIXFROMNUMPY(EXT,TYP,SRCTYPE,NUMPYTYPE) \
259 void EXT##MatrixFromNumpy(arm_matrix_instance_##EXT *s,PyObject *o) \
260 { \
261 s->pData=NULL; \
262 s->numRows=0; \
263 s->numCols=0; \
264 \
265 PyArray_Descr *desct=PyArray_DescrFromType(NUMPYTYPE); \
266 PyArrayObject *cdata = (PyArrayObject *)PyArray_FromAny(o,desct, \
267 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \
268 NULL); \
269 if (cdata) \
270 { \
271 uint32_t memCpyIndex; \
272 SRCTYPE *f=(SRCTYPE*)PyArray_DATA(cdata); \
273 s->numRows=PyArray_DIM(cdata,0); \
274 s->numCols=PyArray_DIM(cdata,1); \
275 uint32_t nb = PyArray_SIZE(cdata); \
276 s->pData = PyMem_Malloc(sizeof(TYP)*nb); \
277 MEMCPY(s->pData ,f,nb,TYP); \
278 Py_DECREF(cdata); \
279 } \
280 \
281 \
282 \
283 }
284
285
286
287 #define CREATEMATRIX(EXT,TYP) \
288 void create##EXT##Matrix(arm_matrix_instance_##EXT *s,uint32_t r,uint32_t c)\
289 { \
290 \
291 s->pData=PyMem_Malloc(sizeof(TYP)*r*c); \
292 s->numRows=r; \
293 s->numCols=c; \
294 }
295
296 #define FREEMATRIX(s) PyMem_Free((s)->pData)
297
298 #define NUMPYVECTORFROMBUFFER(EXT,CTYPE,NUMPYTYPE_FROMC) \
299 PyObject *NumpyVectorFrom##EXT##Buffer(CTYPE *ptr,int nb) \
300 { \
301 npy_intp dims[1]; \
302 const int ND=1; \
303 dims[0]=nb; \
304 \
305 void *pDst=PyMem_Malloc(sizeof(CTYPE) *nb); \
306 memcpy((void*)pDst,(void*)ptr,sizeof(CTYPE)*nb); \
307 \
308 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND, dims, NUMPYTYPE_FROMC, pDst);\
309 PyObject *capsule = PyCapsule_New(pDst, "cmsisdsp capsule",capsule_cleanup); \
310 PyArray_SetBaseObject(OBJ, capsule); \
311 PyObject *pythonResult = Py_BuildValue("O",OBJ); \
312 Py_DECREF(OBJ); \
313 return(pythonResult); \
314 }
315
316
317
318
319 #define NUMPYARRAYFROMMATRIX(EXT,NUMPYTYPE_FROMC) \
320 PyObject *NumpyArrayFrom##EXT##Matrix(arm_matrix_instance_##EXT *mat) \
321 { \
322 npy_intp dims[2]; \
323 dims[0]=mat->numRows; \
324 dims[1]=mat->numCols; \
325 const int ND=2; \
326 PyArrayObject *OBJ=(PyArrayObject*)PyArray_SimpleNewFromData(ND, dims, NUMPYTYPE_FROMC, mat->pData);\
327 PyObject *capsule = PyCapsule_New(mat->pData, "cmsisdsp capsule",capsule_cleanup); \
328 PyArray_SetBaseObject(OBJ, capsule); \
329 PyObject *pythonResult = Py_BuildValue("O",OBJ); \
330 Py_DECREF(OBJ); \
331 return(pythonResult); \
332 }
333
334
335
336
337
338
339 #endif /* #ifndef CMSISMODULE_H */
340