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_bayes"
30 #define MODINITNAME cmsisdsp_bayes
31 
32 #include "cmsisdsp_module.h"
33 
34 
35 
36 NUMPYVECTORFROMBUFFER(f32,float32_t,NPY_FLOAT);
37 
38 
39 
40 typedef struct {
41     PyObject_HEAD
42     arm_gaussian_naive_bayes_instance_f32 *instance;
43 } dsp_arm_gaussian_naive_bayes_instance_f32Object;
44 
45 
46 static void
arm_gaussian_naive_bayes_instance_f32_dealloc(dsp_arm_gaussian_naive_bayes_instance_f32Object * self)47 arm_gaussian_naive_bayes_instance_f32_dealloc(dsp_arm_gaussian_naive_bayes_instance_f32Object* self)
48 {
49     //printf("Dealloc called\n");
50     if (self->instance)
51     {
52 
53        if (self->instance->theta)
54        {
55           PyMem_Free((float32_t*)self->instance->theta);
56        }
57 
58        if (self->instance->sigma)
59        {
60           PyMem_Free((float32_t*)self->instance->sigma);
61        }
62 
63        if (self->instance->classPriors)
64        {
65           PyMem_Free((float32_t*)self->instance->classPriors);
66        }
67 
68        PyMem_Free(self->instance);
69     }
70 
71     Py_TYPE(self)->tp_free((PyObject*)self);
72 }
73 
74 
75 static PyObject *
arm_gaussian_naive_bayes_instance_f32_new(PyTypeObject * type,PyObject * args,PyObject * kwds)76 arm_gaussian_naive_bayes_instance_f32_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
77 {
78     dsp_arm_gaussian_naive_bayes_instance_f32Object *self;
79     //printf("New called\n");
80 
81     self = (dsp_arm_gaussian_naive_bayes_instance_f32Object *)type->tp_alloc(type, 0);
82     //printf("alloc called\n");
83 
84     if (self != NULL) {
85 
86         self->instance = PyMem_Malloc(sizeof(arm_gaussian_naive_bayes_instance_f32));
87         self->instance->theta=NULL;
88         self->instance->sigma=NULL;
89         self->instance->classPriors=NULL;
90 
91     }
92 
93 
94     return (PyObject *)self;
95 }
96 
97 static int
arm_gaussian_naive_bayes_instance_f32_init(dsp_arm_gaussian_naive_bayes_instance_f32Object * self,PyObject * args,PyObject * kwds)98 arm_gaussian_naive_bayes_instance_f32_init(dsp_arm_gaussian_naive_bayes_instance_f32Object *self, PyObject *args, PyObject *kwds)
99 {
100 
101 PyObject *theta=NULL;
102 PyObject *sigma=NULL;
103 PyObject *classPriors=NULL;
104 
105 char *kwlist[] = {
106 "vectorDimension",
107 "numberOfClasses",
108 "theta",
109 "sigma",
110 "classPriors",
111 "epsilon",NULL
112 };
113 
114 if (PyArg_ParseTupleAndKeywords(args, kwds, "|iiOOOf", kwlist,
115   &self->instance->vectorDimension
116 ,&self->instance->numberOfClasses
117 ,&theta
118 ,&sigma
119 ,&classPriors
120 ,&self->instance->epsilon
121 ))
122     {
123 
124       INITARRAYFIELD(theta,NPY_DOUBLE,double,float32_t);
125       INITARRAYFIELD(sigma,NPY_DOUBLE,double,float32_t);
126       INITARRAYFIELD(classPriors,NPY_DOUBLE,double,float32_t);
127     }
128     return 0;
129 }
130 
131 GETFIELD(arm_gaussian_naive_bayes_instance_f32,vectorDimension,"i");
132 GETFIELD(arm_gaussian_naive_bayes_instance_f32,numberOfClasses,"i");
133 GETFIELD(arm_gaussian_naive_bayes_instance_f32,epsilon,"f");
134 
135 
136 static PyMethodDef arm_gaussian_naive_bayes_instance_f32_methods[] = {
137 
138     {"vectorDimension", (PyCFunction) Method_arm_gaussian_naive_bayes_instance_f32_vectorDimension,METH_NOARGS,"vectorDimension"},
139     {"numberOfClasses", (PyCFunction) Method_arm_gaussian_naive_bayes_instance_f32_numberOfClasses,METH_NOARGS,"numberOfClasses"},
140     {"epsilon", (PyCFunction) Method_arm_gaussian_naive_bayes_instance_f32_epsilon,METH_NOARGS,"epsilon"},
141 
142     {NULL}  /* Sentinel */
143 };
144 
145 
146 DSPType(arm_gaussian_naive_bayes_instance_f32,arm_gaussian_naive_bayes_instance_f32_new,arm_gaussian_naive_bayes_instance_f32_dealloc,arm_gaussian_naive_bayes_instance_f32_init,arm_gaussian_naive_bayes_instance_f32_methods);
147 
148 
149 
150 
typeRegistration(PyObject * module)151 void typeRegistration(PyObject *module) {
152 
153 
154 
155   ADDTYPE(arm_gaussian_naive_bayes_instance_f32);
156 
157 
158 }
159 
160 
161 static PyObject *
cmsis_arm_gaussian_naive_bayes_predict_f32(PyObject * obj,PyObject * args)162 cmsis_arm_gaussian_naive_bayes_predict_f32(PyObject *obj, PyObject *args)
163 {
164 
165   PyObject *S=NULL; // input
166   PyObject *pSrc=NULL; // input
167   float32_t *pSrc_converted=NULL; // input
168   float32_t *pDst=NULL; // output
169   uint32_t nbClasses; // input
170 
171   if (PyArg_ParseTuple(args,"OO",&S,&pSrc))
172   {
173 
174     dsp_arm_gaussian_naive_bayes_instance_f32Object *selfS = (dsp_arm_gaussian_naive_bayes_instance_f32Object *)S;
175     GETARGUMENT(pSrc,NPY_DOUBLE,double,float32_t);
176 
177     nbClasses=selfS->instance->numberOfClasses;
178 
179 
180     pDst=PyMem_Malloc(sizeof(float32_t)*nbClasses);
181     float32_t *temp=PyMem_Malloc(sizeof(float32_t)*nbClasses);
182 
183 
184     uint32_t res=arm_gaussian_naive_bayes_predict_f32(selfS->instance,pSrc_converted,pDst,temp);
185  FLOATARRAY1(pDstOBJ,nbClasses,pDst);
186 
187     PyObject *pythonResult = Py_BuildValue("Ok",pDstOBJ,res);
188 
189     FREEARGUMENT(pSrc_converted);
190     PyMem_Free(temp);
191     Py_DECREF(pDstOBJ);
192     return(pythonResult);
193 
194   }
195   return(NULL);
196 }
197 
198 
199 
200 static PyMethodDef CMSISDSPMethods[] = {
201 
202 
203 
204 {"arm_gaussian_naive_bayes_predict_f32",  cmsis_arm_gaussian_naive_bayes_predict_f32, METH_VARARGS,""},
205 
206 
207 
208     {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
209     {NULL, NULL, 0, NULL}        /* Sentinel */
210 };
211 
212 #ifdef IS_PY3K
cmsisdsp_traverse(PyObject * m,visitproc visit,void * arg)213 static int cmsisdsp_traverse(PyObject *m, visitproc visit, void *arg) {
214     Py_VISIT(GETSTATE(m)->error);
215     return 0;
216 }
217 
cmsisdsp_clear(PyObject * m)218 static int cmsisdsp_clear(PyObject *m) {
219     Py_CLEAR(GETSTATE(m)->error);
220     return 0;
221 }
222 
223 
224 static struct PyModuleDef moduledef = {
225         PyModuleDef_HEAD_INIT,
226         MODNAME,
227         NULL,
228         sizeof(struct module_state),
229         CMSISDSPMethods,
230         NULL,
231         cmsisdsp_traverse,
232         cmsisdsp_clear,
233         NULL
234 };
235 
236 #define INITERROR return NULL
237 
238 PyMODINIT_FUNC
CAT(PyInit_,MODINITNAME)239 CAT(PyInit_,MODINITNAME)(void)
240 
241 
242 #else
243 #define INITERROR return
244 
245 void CAT(init,MODINITNAME)(void)
246 #endif
247 {
248     import_array();
249 
250   #ifdef IS_PY3K
251     PyObject *module = PyModule_Create(&moduledef);
252   #else
253     PyObject *module = Py_InitModule(MODNAME, CMSISDSPMethods);
254   #endif
255 
256   if (module == NULL)
257       INITERROR;
258   struct module_state *st = GETSTATE(module);
259 
260   st->error = PyErr_NewException(MODNAME".Error", NULL, NULL);
261   if (st->error == NULL) {
262       Py_DECREF(module);
263       INITERROR;
264   }
265 
266 
267   typeRegistration(module);
268 
269   #ifdef IS_PY3K
270     return module;
271   #endif
272 }