1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Python Wrapper
3 * Title: cmsismodule.h
4 * Description: C code for the CMSIS-DSP Python wrapper
5 *
6 * $Date: 27 April 2021
7 * $Revision: V1.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
29 #define MODNAME "cmsisdsp_distance"
30 #define MODINITNAME cmsisdsp_distance
31
32 #include "cmsisdsp_module.h"
33 MATRIXFROMNUMPY(f32,float32_t,double,NPY_DOUBLE);
34 CREATEMATRIX(f32,float32_t);
35 NUMPYARRAYFROMMATRIX(f32,NPY_FLOAT);
36
37 MATRIXFROMNUMPY(q7,q7_t,int8_t,NPY_BYTE);
38 CREATEMATRIX(q7,q7_t);
39 NUMPYARRAYFROMMATRIX(q7,NPY_BYTE);
40
41
42 NUMPYVECTORFROMBUFFER(f32,float32_t,NPY_FLOAT);
43
44
typeRegistration(PyObject * module)45 void typeRegistration(PyObject *module) {
46
47
48 }
49
50 #define FLOATDIST(NAME) \
51 static PyObject * \
52 cmsis_arm_##NAME##_f32(PyObject *obj, PyObject *args) \
53 { \
54 \
55 PyObject *pSrcA=NULL; \
56 float32_t *pSrcA_converted=NULL; \
57 PyObject *pSrcB=NULL; \
58 float32_t *pSrcB_converted=NULL; \
59 uint32_t blockSize; \
60 float32_t result; \
61 \
62 if (PyArg_ParseTuple(args,"OO",&pSrcA,&pSrcB)) \
63 { \
64 \
65 GETARGUMENT(pSrcA,NPY_DOUBLE,double,float32_t); \
66 GETARGUMENT(pSrcB,NPY_DOUBLE,double,float32_t); \
67 blockSize = arraySizepSrcA ; \
68 \
69 \
70 \
71 result=arm_##NAME##_f32(pSrcA_converted,pSrcB_converted,blockSize);\
72 PyObject* resultOBJ=Py_BuildValue("f",result); \
73 \
74 PyObject *pythonResult = Py_BuildValue("O",resultOBJ); \
75 \
76 FREEARGUMENT(pSrcA_converted); \
77 FREEARGUMENT(pSrcB_converted); \
78 Py_DECREF(resultOBJ); \
79 return(pythonResult); \
80 \
81 } \
82 return(NULL); \
83 }
84
85 #define FLOAT64DIST(NAME) \
86 static PyObject * \
87 cmsis_arm_##NAME##_f64(PyObject *obj, PyObject *args) \
88 { \
89 \
90 PyObject *pSrcA=NULL; \
91 float64_t *pSrcA_converted=NULL; \
92 PyObject *pSrcB=NULL; \
93 float64_t *pSrcB_converted=NULL; \
94 uint32_t blockSize; \
95 float64_t result; \
96 \
97 if (PyArg_ParseTuple(args,"OO",&pSrcA,&pSrcB)) \
98 { \
99 \
100 GETARGUMENT(pSrcA,NPY_DOUBLE,double,float64_t); \
101 GETARGUMENT(pSrcB,NPY_DOUBLE,double,float64_t); \
102 blockSize = arraySizepSrcA ; \
103 \
104 \
105 \
106 result=arm_##NAME##_f64(pSrcA_converted,pSrcB_converted,blockSize);\
107 PyObject* resultOBJ=Py_BuildValue("d",result); \
108 \
109 PyObject *pythonResult = Py_BuildValue("O",resultOBJ); \
110 \
111 FREEARGUMENT(pSrcA_converted); \
112 FREEARGUMENT(pSrcB_converted); \
113 Py_DECREF(resultOBJ); \
114 return(pythonResult); \
115 \
116 } \
117 return(NULL); \
118 }
119
120 FLOAT64DIST(chebyshev_distance);
121 FLOAT64DIST(cityblock_distance);
122 FLOAT64DIST(cosine_distance);
123 FLOAT64DIST(euclidean_distance);
124
125
126 FLOATDIST(braycurtis_distance);
127 FLOATDIST(canberra_distance);
128 FLOATDIST(chebyshev_distance);
129 FLOATDIST(cityblock_distance);
130 FLOATDIST(correlation_distance);
131 FLOATDIST(cosine_distance);
132 FLOATDIST(euclidean_distance);
133 FLOATDIST(jensenshannon_distance);
134
135 static PyObject *
cmsis_arm_minkowski_distance_f32(PyObject * obj,PyObject * args)136 cmsis_arm_minkowski_distance_f32(PyObject *obj, PyObject *args)
137 {
138
139 PyObject *pSrcA=NULL;
140 float32_t *pSrcA_converted=NULL;
141 PyObject *pSrcB=NULL;
142 float32_t *pSrcB_converted=NULL;
143 int32_t w;
144 uint32_t blockSize;
145 float32_t result;
146
147 if (PyArg_ParseTuple(args,"OOi",&pSrcA,&pSrcB,&w))
148 {
149
150 GETARGUMENT(pSrcA,NPY_DOUBLE,double,float32_t);
151 GETARGUMENT(pSrcB,NPY_DOUBLE,double,float32_t);
152
153 blockSize = arraySizepSrcA ;
154
155
156
157 result=arm_minkowski_distance_f32(pSrcA_converted,pSrcB_converted,w,blockSize);
158 PyObject* resultOBJ=Py_BuildValue("f",result);
159
160 PyObject *pythonResult = Py_BuildValue("O",resultOBJ);
161
162 FREEARGUMENT(pSrcA_converted);
163 FREEARGUMENT(pSrcB_converted);
164
165 Py_DECREF(resultOBJ);
166 return(pythonResult);
167
168 }
169 return(NULL);
170 }
171
172
173 #define INTDIST(NAME) \
174 static PyObject * \
175 cmsis_arm_##NAME (PyObject *obj, PyObject *args) \
176 { \
177 \
178 PyObject *pSrcA=NULL; \
179 uint32_t *pSrcA_converted=NULL; \
180 PyObject *pSrcB=NULL; \
181 uint32_t *pSrcB_converted=NULL; \
182 uint32_t blockSize; \
183 float32_t result; \
184 \
185 \
186 if (PyArg_ParseTuple(args,"OOi",&pSrcA,&pSrcB,&blockSize)) \
187 { \
188 \
189 GETARGUMENT(pSrcA,NPY_UINT32,uint32_t,uint32_t); \
190 GETARGUMENT(pSrcB,NPY_UINT32,uint32_t,uint32_t); \
191 \
192 \
193 \
194 result=arm_##NAME (pSrcA_converted,pSrcB_converted,blockSize); \
195 PyObject* resultOBJ=Py_BuildValue("f",result); \
196 \
197 PyObject *pythonResult = Py_BuildValue("O",resultOBJ); \
198 \
199 FREEARGUMENT(pSrcA_converted); \
200 FREEARGUMENT(pSrcB_converted); \
201 Py_DECREF(resultOBJ); \
202 return(pythonResult); \
203 \
204 } \
205 return(NULL); \
206 }
207
208
209 INTDIST(dice_distance);
210 INTDIST(hamming_distance);
211 INTDIST(jaccard_distance);
212 INTDIST(kulsinski_distance);
213 INTDIST(rogerstanimoto_distance);
214 INTDIST(russellrao_distance);
215 INTDIST(sokalmichener_distance);
216 INTDIST(sokalsneath_distance);
217 INTDIST(yule_distance);
218
219 static PyObject *
cmsis_arm_dtw_init_window_q7(PyObject * obj,PyObject * args)220 cmsis_arm_dtw_init_window_q7(PyObject *obj,
221 PyObject *args)
222 {
223
224 PyObject *pSrc=NULL; // input
225 int32_t winType;
226 int32_t winSize;
227 arm_matrix_instance_q7 pSrc_converted; // input
228
229
230 if (PyArg_ParseTuple(args,"iiO",&winType,&winSize,&pSrc))
231 {
232
233 q7MatrixFromNumpy(&pSrc_converted,pSrc);
234 uint32_t row = pSrc_converted.numCols ;
235 uint32_t column = pSrc_converted.numRows ;
236
237 arm_status returnValue =
238 arm_dtw_init_window_q7(winType,
239 winSize,
240 &pSrc_converted
241 );
242 PyObject* theReturnOBJ=Py_BuildValue("i",returnValue);
243 PyObject* dstOBJ=NumpyArrayFromq7Matrix(&pSrc_converted);
244
245 PyObject *pythonResult = Py_BuildValue("OO",theReturnOBJ,dstOBJ);
246
247 Py_DECREF(theReturnOBJ);
248 Py_DECREF(dstOBJ);
249 return(pythonResult);
250
251 }
252 Py_RETURN_NONE;
253 }
254
255 static PyObject *
cmsis_arm_dtw_distance_f32(PyObject * obj,PyObject * args)256 cmsis_arm_dtw_distance_f32(PyObject *obj,
257 PyObject *args)
258 {
259
260 PyObject *pDist=NULL; // input
261 arm_matrix_instance_f32 pDist_converted; // input
262
263 PyObject *pWin=NULL; // input
264 arm_matrix_instance_q7 pWin_converted; // input
265 arm_matrix_instance_q7 *pWinMatrix;
266
267 arm_matrix_instance_f32 dtw_converted;
268
269
270 if (PyArg_ParseTuple(args,"OO",&pDist,&pWin))
271 {
272
273 f32MatrixFromNumpy(&pDist_converted,pDist);
274 if (pWin != Py_None)
275 {
276 q7MatrixFromNumpy(&pWin_converted,pWin);
277 pWinMatrix = &pWin_converted;
278 }
279 else
280 {
281 pWinMatrix = NULL;
282 }
283
284 uint32_t column = pDist_converted.numCols ;
285 uint32_t row = pDist_converted.numRows ;
286 createf32Matrix(&dtw_converted,row,column);
287 float32_t distance;
288
289 arm_status returnValue =
290 arm_dtw_distance_f32(&pDist_converted,
291 pWinMatrix,
292 &dtw_converted,
293 &distance
294 );
295
296
297 PyObject* theReturnOBJ=Py_BuildValue("i",returnValue);
298 PyObject* distOBJ=Py_BuildValue("f",distance);
299
300 PyObject* dstOBJ=NumpyArrayFromf32Matrix(&dtw_converted);
301
302
303 PyObject *pythonResult = Py_BuildValue("OOO",theReturnOBJ,distOBJ,dstOBJ);
304
305 Py_DECREF(theReturnOBJ);
306 Py_DECREF(distOBJ);
307
308 FREEMATRIX(&pDist_converted);
309 if (pWinMatrix)
310 {
311 FREEMATRIX(pWinMatrix);
312 }
313 Py_DECREF(dstOBJ);
314
315 return(pythonResult);
316
317 }
318 Py_RETURN_NONE;
319 }
320
321 static PyObject *
cmsis_arm_dtw_path_f32(PyObject * obj,PyObject * args)322 cmsis_arm_dtw_path_f32(PyObject *obj,
323 PyObject *args)
324 {
325 PyObject *pCost=NULL; // input
326 arm_matrix_instance_f32 pCost_converted; // input
327 int16_t *pDst=NULL; // output
328
329 if (PyArg_ParseTuple(args,"O",&pCost))
330 {
331 f32MatrixFromNumpy(&pCost_converted,pCost);
332
333 uint32_t pathLength;
334 int32_t blockSize;
335 blockSize=2*(pCost_converted.numRows+pCost_converted.numCols);
336 pDst=PyMem_Malloc(sizeof(int16_t)*blockSize);
337
338
339 arm_dtw_path_f32(&pCost_converted,
340 pDst,
341 &pathLength);
342
343 INT16ARRAY1(pDstOBJ,2*pathLength,pDst);
344
345 PyObject *pythonResult = Py_BuildValue("O",pDstOBJ);
346
347 FREEMATRIX(&pCost_converted);
348 Py_DECREF(pDstOBJ);
349 return(pythonResult);
350 }
351 Py_RETURN_NONE;
352 }
353
354 static PyMethodDef CMSISDSPMethods[] = {
355
356 {"arm_braycurtis_distance_f32", cmsis_arm_braycurtis_distance_f32, METH_VARARGS,""},
357 {"arm_canberra_distance_f32" , cmsis_arm_canberra_distance_f32, METH_VARARGS,""},
358 {"arm_chebyshev_distance_f32" , cmsis_arm_chebyshev_distance_f32, METH_VARARGS,""},
359 {"arm_chebyshev_distance_f64" , cmsis_arm_chebyshev_distance_f64, METH_VARARGS,""},
360
361 {"arm_cityblock_distance_f32", cmsis_arm_cityblock_distance_f32, METH_VARARGS,""},
362 {"arm_cityblock_distance_f64", cmsis_arm_cityblock_distance_f64, METH_VARARGS,""},
363
364 {"arm_correlation_distance_f32", cmsis_arm_correlation_distance_f32, METH_VARARGS,""},
365
366 {"arm_cosine_distance_f32", cmsis_arm_cosine_distance_f32, METH_VARARGS,""},
367 {"arm_cosine_distance_f64", cmsis_arm_cosine_distance_f64, METH_VARARGS,""},
368
369 {"arm_euclidean_distance_f32", cmsis_arm_euclidean_distance_f32, METH_VARARGS,""},
370 {"arm_euclidean_distance_f64", cmsis_arm_euclidean_distance_f64, METH_VARARGS,""},
371
372 {"arm_jensenshannon_distance_f32", cmsis_arm_jensenshannon_distance_f32, METH_VARARGS,""},
373 {"arm_minkowski_distance_f32", cmsis_arm_minkowski_distance_f32, METH_VARARGS,""},
374
375 {"arm_dice_distance",cmsis_arm_dice_distance, METH_VARARGS,""},
376 {"arm_hamming_distance",cmsis_arm_hamming_distance, METH_VARARGS,""},
377 {"arm_jaccard_distance",cmsis_arm_jaccard_distance, METH_VARARGS,""},
378 {"arm_kulsinski_distance",cmsis_arm_kulsinski_distance, METH_VARARGS,""},
379 {"arm_rogerstanimoto_distance",cmsis_arm_rogerstanimoto_distance, METH_VARARGS,""},
380 {"arm_russellrao_distance",cmsis_arm_russellrao_distance, METH_VARARGS,""},
381 {"arm_sokalmichener_distance",cmsis_arm_sokalmichener_distance, METH_VARARGS,""},
382 {"arm_sokalsneath_distance",cmsis_arm_sokalsneath_distance, METH_VARARGS,""},
383 {"arm_yule_distance",cmsis_arm_yule_distance, METH_VARARGS,""},
384
385 {"arm_dtw_init_window_q7", cmsis_arm_dtw_init_window_q7, METH_VARARGS,""},
386 {"arm_dtw_distance_f32", cmsis_arm_dtw_distance_f32, METH_VARARGS,""},
387 {"arm_dtw_path_f32", cmsis_arm_dtw_path_f32, METH_VARARGS,""},
388
389 {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
390 {NULL, NULL, 0, NULL} /* Sentinel */
391 };
392
393 #ifdef IS_PY3K
cmsisdsp_traverse(PyObject * m,visitproc visit,void * arg)394 static int cmsisdsp_traverse(PyObject *m, visitproc visit, void *arg) {
395 Py_VISIT(GETSTATE(m)->error);
396 return 0;
397 }
398
cmsisdsp_clear(PyObject * m)399 static int cmsisdsp_clear(PyObject *m) {
400 Py_CLEAR(GETSTATE(m)->error);
401 return 0;
402 }
403
404
405 static struct PyModuleDef moduledef = {
406 PyModuleDef_HEAD_INIT,
407 MODNAME,
408 NULL,
409 sizeof(struct module_state),
410 CMSISDSPMethods,
411 NULL,
412 cmsisdsp_traverse,
413 cmsisdsp_clear,
414 NULL
415 };
416
417 #define INITERROR return NULL
418
419 PyMODINIT_FUNC
CAT(PyInit_,MODINITNAME)420 CAT(PyInit_,MODINITNAME)(void)
421
422
423 #else
424 #define INITERROR return
425
426 void CAT(init,MODINITNAME)(void)
427 #endif
428 {
429 import_array();
430
431 #ifdef IS_PY3K
432 PyObject *module = PyModule_Create(&moduledef);
433 #else
434 PyObject *module = Py_InitModule(MODNAME, CMSISDSPMethods);
435 #endif
436
437 if (module == NULL)
438 INITERROR;
439 struct module_state *st = GETSTATE(module);
440
441 st->error = PyErr_NewException(MODNAME".Error", NULL, NULL);
442 if (st->error == NULL) {
443 Py_DECREF(module);
444 INITERROR;
445 }
446
447
448 typeRegistration(module);
449
450 #ifdef IS_PY3K
451 return module;
452 #endif
453 }
454