/* ---------------------------------------------------------------------- * Project: CMSIS DSP Python Wrapper * Title: cmsismodule.c * Description: C code for the CMSIS-DSP Python wrapper * * $Date: 25. March 2019 * $Revision: V0.0.1 * * Target Processor: Cortex-M cores * -------------------------------------------------------------------- */ /* * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define NPY_NO_DEPRECATED_API NPY_1_15_API_VERSION #ifdef WIN #pragma warning( disable : 4013 ) #pragma warning( disable : 4244 ) #endif #include #define MAX(A,B) (A) < (B) ? (B) : (A) #define CAT1(A,B) A##B #define CAT(A,B) CAT1(A,B) #ifdef CMSISDSP #include "arm_math.h" #define MODNAME "cmsisdsp" #define MODINITNAME cmsisdsp #endif #include #include #if PY_MAJOR_VERSION >= 3 #define IS_PY3K #endif struct module_state { PyObject *error; }; #if PY_MAJOR_VERSION >= 3 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) #else #define GETSTATE(m) (&_state) static struct module_state _state; #endif static PyObject * error_out(PyObject *m) { struct module_state *st = GETSTATE(m); PyErr_SetString(st->error, "something bad happened"); return NULL; } #define MLTYPE(name,thenewfunc,deallocfunc,initfunc,methods)\ static PyTypeObject ml_##name##Type = { \ PyVarObject_HEAD_INIT(NULL, 0) \ .tp_name=MODNAME".##name", \ .tp_basicsize = sizeof(ml_##name##Object), \ .tp_itemsize = 0, \ .tp_dealloc = (destructor)deallocfunc, \ .tp_flags = Py_TPFLAGS_DEFAULT, \ .tp_doc = #name, \ .tp_init = (initproc)initfunc, \ .tp_new = (newfunc)thenewfunc, \ .tp_methods = methods \ }; #define MEMCPY(DST,SRC,NB,FORMAT) \ for(memCpyIndex = 0; memCpyIndex < (NB) ; memCpyIndex++)\ { \ (DST)[memCpyIndex] = (FORMAT)(SRC)[memCpyIndex]; \ } #define GETFIELD(NAME,FIELD,FORMAT) \ static PyObject * \ Method_##NAME##_##FIELD(ml_##NAME##Object *self, PyObject *ignored)\ { \ return(Py_BuildValue(FORMAT,self->instance->FIELD)); \ } #define GETFIELDARRAY(NAME,FIELD,FORMAT) \ static PyObject * \ Method_##NAME##_##FIELD(ml_##NAME##Object *self, PyObject *ignored)\ { \ return(specific_##NAME##_##FIELD(self->instance)); \ } #define INITARRAYFIELD(FIELD,FORMAT,SRCFORMAT,DSTFORMAT) \ if (FIELD) \ { \ PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \ PyArrayObject *FIELD##c = (PyArrayObject *)PyArray_FromAny(FIELD,desct,\ 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \ NULL); \ if (FIELD##c) \ { \ uint32_t memCpyIndex; \ SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(FIELD##c); \ uint32_t n = PyArray_SIZE(FIELD##c); \ self->instance->FIELD =PyMem_Malloc(sizeof(DSTFORMAT)*n); \ MEMCPY(self->instance->FIELD ,f,n,DSTFORMAT); \ Py_DECREF(FIELD##c); \ } \ } #define GETCARRAY(PYVAR,CVAR,FORMAT,SRCFORMAT,DSTFORMAT) \ if (PYVAR) \ { \ PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \ PyArrayObject *PYVAR##c = (PyArrayObject *)PyArray_FromAny(PYVAR,desct,\ 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \ NULL); \ if (PYVAR##c) \ { \ uint32_t memCpyIndex; \ SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(PYVAR##c); \ uint32_t n = PyArray_SIZE(PYVAR##c); \ CVAR =PyMem_Malloc(sizeof(DSTFORMAT)*n); \ MEMCPY(CVAR ,f,n,DSTFORMAT); \ Py_DECREF(PYVAR##c); \ } \ } #define GETARGUMENT(FIELD,FORMAT,SRCFORMAT,DSTFORMAT) \ uint32_t arraySize##FIELD=0; \ if (FIELD) \ { \ PyArray_Descr *desct=PyArray_DescrFromType(FORMAT); \ PyArrayObject *FIELD##c = (PyArrayObject *)PyArray_FromAny(FIELD,desct, \ 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \ NULL); \ if (FIELD##c) \ { \ uint32_t memCpyIndex; \ SRCFORMAT *f=(SRCFORMAT*)PyArray_DATA(FIELD##c); \ arraySize##FIELD = PyArray_SIZE(FIELD##c); \ FIELD##_converted =PyMem_Malloc(sizeof(DSTFORMAT)*arraySize##FIELD);\ MEMCPY(FIELD##_converted ,f,arraySize##FIELD,DSTFORMAT); \ Py_DECREF(FIELD##c); \ } \ } #define FREEARGUMENT(FIELD) \ PyMem_Free(FIELD) #ifdef IS_PY3K #define ADDTYPE(name) \ if (PyType_Ready(&ml_##name##Type) < 0) \ return; \ \ Py_INCREF(&ml_##name##Type); \ PyModule_AddObject(module, #name, (PyObject *)&ml_##name##Type); #else #define ADDTYPE(name) \ if (PyType_Ready(&ml_##name##Type) < 0) \ return; \ \ Py_INCREF(&ml_##name##Type); \ PyModule_AddObject(module, #name, (PyObject *)&ml_##name##Type); #endif #define FLOATARRAY2(OBJ,NB1,NB2,DATA) \ npy_intp dims[2]; \ dims[0]=NB1; \ dims[1]=NB2; \ const int ND=2; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_FLOAT, DATA); #define FLOATARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_FLOAT, DATA); #define FLOAT64ARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_DOUBLE, DATA); #define UINT32ARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_UINT32, DATA); #define INT32ARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_INT32, DATA); #define INT16ARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_INT16, DATA); #define INT8ARRAY1(OBJ,NB1,DATA) \ npy_intp dims[1]; \ dims[0]=NB1; \ const int ND=1; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NPY_BYTE, DATA); #define MATRIXFROMNUMPY(EXT,TYP,SRCTYPE,NUMPYTYPE) \ arm_matrix_instance_##EXT *EXT##MatrixFromNumpy(PyObject *o) \ { \ arm_matrix_instance_##EXT *s; \ \ s=PyMem_Malloc(sizeof(arm_matrix_instance_##EXT)); \ s->pData=NULL; \ s->numRows=0; \ s->numCols=0; \ \ PyArray_Descr *desct=PyArray_DescrFromType(NUMPYTYPE); \ PyArrayObject *cdata = (PyArrayObject *)PyArray_FromAny(o,desct, \ 1,0,NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_FORCECAST, \ NULL); \ if (cdata) \ { \ uint32_t memCpyIndex; \ SRCTYPE *f=(SRCTYPE*)PyArray_DATA(cdata); \ s->numRows=PyArray_DIM(cdata,0); \ s->numCols=PyArray_DIM(cdata,1); \ uint32_t nb = PyArray_SIZE(cdata); \ s->pData = PyMem_Malloc(sizeof(TYP)*nb); \ MEMCPY(s->pData ,f,nb,TYP); \ Py_DECREF(cdata); \ } \ \ \ return(s); \ \ } MATRIXFROMNUMPY(f32,float32_t,double,NPY_DOUBLE); MATRIXFROMNUMPY(f64,float64_t,double,NPY_DOUBLE); MATRIXFROMNUMPY(q31,q31_t,int32_t,NPY_INT32); MATRIXFROMNUMPY(q15,q15_t,int16_t,NPY_INT16); #define CREATEMATRIX(EXT,TYP) \ arm_matrix_instance_##EXT *create##EXT##Matrix(uint32_t r,uint32_t c)\ { \ arm_matrix_instance_##EXT *s; \ \ s=PyMem_Malloc(sizeof(arm_matrix_instance_##EXT)); \ s->pData=PyMem_Malloc(sizeof(TYP)*r*c); \ s->numRows=r; \ s->numCols=c; \ return(s); \ } CREATEMATRIX(f32,float32_t); CREATEMATRIX(f64,float64_t); CREATEMATRIX(q31,q31_t); CREATEMATRIX(q15,q15_t); #define NUMPYARRAYFROMMATRIX(EXT,NUMPYTYPE_FROMC) \ PyObject *NumpyArrayFrom##EXT##Matrix(arm_matrix_instance_##EXT *mat) \ { \ npy_intp dims[2]; \ dims[0]=mat->numRows; \ dims[1]=mat->numCols; \ const int ND=2; \ PyObject *OBJ=PyArray_SimpleNewFromData(ND, dims, NUMPYTYPE_FROMC, mat->pData);\ return(OBJ); \ } NUMPYARRAYFROMMATRIX(f32,NPY_FLOAT); NUMPYARRAYFROMMATRIX(f64,NPY_DOUBLE); NUMPYARRAYFROMMATRIX(q31,NPY_INT32); NUMPYARRAYFROMMATRIX(q15,NPY_INT16); //#include "specific.h" #include "cmsismodule.h" #if 0 static PyObject *cmsisml_test(PyObject *obj, PyObject *args) { ml_arm_svm_linear_instance_f32Object *self=NULL; PyObject *svm, *vector=NULL; if (!PyArg_ParseTuple(args, "OO", &svm,&vector)) return NULL; self=(ml_arm_svm_linear_instance_f32Object*)svm; if (self) { if (self->instance) { int result; float32_t *input=NULL; GETCARRAY(vector,input,NPY_DOUBLE,double,float32_t); arm_svm_linear_predict_f32(self->instance,input,&result); /* printf("Dual\n"); for(int i = 0 ; i < self->instance->nbOfSupportVectors ; i++) { printf("%f\n",self->instance->dualCoefficients[i]); } printf("Vectors\n"); int k=0; for(int i = 0 ; i < self->instance->nbOfSupportVectors ; i++) { printf("Vector %d\n",i); for(int j = 0 ; j < self->instance->vectorDimension ; j++) { printf("%f\n",self->instance->supportVectors[k]); k++; } } printf("Classes\n"); for(int i = 0 ; i < 2 ; i++) { printf("%d\n",self->instance->classes[i]); } printf("Intercept %f\n",self->instance->intercept); */ PyMem_Free(input); return(Py_BuildValue("i",result)); } } return(Py_BuildValue("i",-1)); } #endif #ifdef IS_PY3K static int cmsisml_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(GETSTATE(m)->error); return 0; } static int cmsisml_clear(PyObject *m) { Py_CLEAR(GETSTATE(m)->error); return 0; } static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, MODNAME, NULL, sizeof(struct module_state), CMSISMLMethods, NULL, cmsisml_traverse, cmsisml_clear, NULL }; #define INITERROR return NULL PyMODINIT_FUNC CAT(PyInit_,MODINITNAME)(void) #else #define INITERROR return void CAT(init,MODINITNAME)(void) #endif { import_array(); #ifdef IS_PY3K PyObject *module = PyModule_Create(&moduledef); #else PyObject *module = Py_InitModule(MODNAME, CMSISMLMethods); #endif if (module == NULL) INITERROR; struct module_state *st = GETSTATE(module); st->error = PyErr_NewException(MODNAME".Error", NULL, NULL); if (st->error == NULL) { Py_DECREF(module); INITERROR; } typeRegistration(module); #ifdef IS_PY3K return module; #endif }