1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_naive_gaussian_bayes_predict_f16
4 * Description: Naive Gaussian Bayesian Estimator
5 *
6 * $Date: 23 April 2021
7 * $Revision: V1.9.0
8 *
9 * Target Processor: Cortex-M and Cortex-A 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 #include "dsp/bayes_functions_f16.h"
30
31 #if defined(ARM_FLOAT16_SUPPORTED)
32
33 #include <limits.h>
34 #include <math.h>
35
36 #define PI_F 3.1415926535897932384626433832795f16
37
38 /**
39 * @addtogroup groupBayes
40 * @{
41 */
42
43 /**
44 * @brief Naive Gaussian Bayesian Estimator
45 *
46 * @param[in] *S points to a naive bayes instance structure
47 * @param[in] *in points to the elements of the input vector.
48 * @param[out] *pOutputProbabilities points to a buffer of length numberOfClasses containing estimated probabilities
49 * @param[out] *pBufferB points to a temporary buffer of length numberOfClasses
50 * @return The predicted class
51 *
52 *
53 */
54
55 #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE)
56
57 #include "arm_helium_utils.h"
58 #include "arm_vec_math_f16.h"
59
arm_gaussian_naive_bayes_predict_f16(const arm_gaussian_naive_bayes_instance_f16 * S,const float16_t * in,float16_t * pOutputProbabilities,float16_t * pBufferB)60 uint32_t arm_gaussian_naive_bayes_predict_f16(const arm_gaussian_naive_bayes_instance_f16 *S,
61 const float16_t * in,
62 float16_t *pOutputProbabilities,
63 float16_t *pBufferB
64 )
65 {
66 uint32_t nbClass;
67 const float16_t *pTheta = S->theta;
68 const float16_t *pSigma = S->sigma;
69 float16_t *buffer = pOutputProbabilities;
70 const float16_t *pIn = in;
71 float16_t result;
72 f16x8_t vsigma;
73 _Float16 tmp;
74 f16x8_t vacc1, vacc2;
75 uint32_t index;
76 float16_t *logclassPriors=pBufferB;
77 float16_t *pLogPrior = logclassPriors;
78
79 arm_vlog_f16((float16_t *) S->classPriors, logclassPriors, S->numberOfClasses);
80
81 pTheta = S->theta;
82 pSigma = S->sigma;
83
84 for (nbClass = 0; nbClass < S->numberOfClasses; nbClass++) {
85 pIn = in;
86
87 vacc1 = vdupq_n_f16(0.0f16);
88 vacc2 = vdupq_n_f16(0.0f16);
89
90 uint32_t blkCnt =S->vectorDimension >> 3;
91 while (blkCnt > 0U) {
92 f16x8_t vinvSigma, vtmp;
93
94 vsigma = vaddq_n_f16(vld1q(pSigma), S->epsilon);
95 vacc1 = vaddq(vacc1, vlogq_f16(vmulq_n_f16(vsigma, 2.0f16 * (_Float16)PI)));
96
97 vinvSigma = vrecip_medprec_f16(vsigma);
98
99 vtmp = vsubq(vld1q(pIn), vld1q(pTheta));
100 /* squaring */
101 vtmp = vmulq(vtmp, vtmp);
102
103 vacc2 = vfmaq(vacc2, vtmp, vinvSigma);
104
105 pIn += 8;
106 pTheta += 8;
107 pSigma += 8;
108 blkCnt--;
109 }
110
111 blkCnt = S->vectorDimension & 7;
112 if (blkCnt > 0U) {
113 mve_pred16_t p0 = vctp16q(blkCnt);
114 f16x8_t vinvSigma, vtmp;
115
116 vsigma = vaddq_n_f16(vld1q(pSigma), S->epsilon);
117 vacc1 =
118 vaddq_m_f16(vacc1, vacc1, vlogq_f16(vmulq_n_f16(vsigma, 2.0f16 * (_Float16)PI)), p0);
119
120 vinvSigma = vrecip_medprec_f16(vsigma);
121
122 vtmp = vsubq(vld1q(pIn), vld1q(pTheta));
123 /* squaring */
124 vtmp = vmulq(vtmp, vtmp);
125
126 vacc2 = vfmaq_m_f16(vacc2, vtmp, vinvSigma, p0);
127
128 pTheta += blkCnt;
129 pSigma += blkCnt;
130 }
131
132 tmp = -0.5f16 * (_Float16)vecAddAcrossF16Mve(vacc1);
133 tmp -= 0.5f16 * (_Float16)vecAddAcrossF16Mve(vacc2);
134
135 *buffer = tmp + *pLogPrior++;
136 buffer++;
137 }
138
139 arm_max_f16(pOutputProbabilities, S->numberOfClasses, &result, &index);
140
141 return (index);
142 }
143
144 #else
145
arm_gaussian_naive_bayes_predict_f16(const arm_gaussian_naive_bayes_instance_f16 * S,const float16_t * in,float16_t * pOutputProbabilities,float16_t * pBufferB)146 uint32_t arm_gaussian_naive_bayes_predict_f16(const arm_gaussian_naive_bayes_instance_f16 *S,
147 const float16_t * in,
148 float16_t *pOutputProbabilities,
149 float16_t *pBufferB)
150 {
151 uint32_t nbClass;
152 uint32_t nbDim;
153 const float16_t *pPrior = S->classPriors;
154 const float16_t *pTheta = S->theta;
155 const float16_t *pSigma = S->sigma;
156 float16_t *buffer = pOutputProbabilities;
157 const float16_t *pIn=in;
158 float16_t result;
159 _Float16 sigma;
160 _Float16 tmp;
161 _Float16 acc1,acc2;
162 uint32_t index;
163 (void)pBufferB;
164
165 pTheta=S->theta;
166 pSigma=S->sigma;
167
168 for(nbClass = 0; nbClass < S->numberOfClasses; nbClass++)
169 {
170
171
172 pIn = in;
173
174 tmp = 0.0f16;
175 acc1 = 0.0f16;
176 acc2 = 0.0f16;
177 for(nbDim = 0; nbDim < S->vectorDimension; nbDim++)
178 {
179 sigma = *pSigma + S->epsilon;
180 acc1 += logf(2.0f16 * (_Float16)PI_F * sigma);
181 acc2 += (*pIn - *pTheta) * (*pIn - *pTheta) / sigma;
182
183 pIn++;
184 pTheta++;
185 pSigma++;
186 }
187
188 tmp = -0.5f16 * acc1;
189 tmp -= 0.5f16 * acc2;
190
191
192 *buffer = tmp + logf(*pPrior++);
193 buffer++;
194 }
195
196 arm_max_f16(pOutputProbabilities,S->numberOfClasses,&result,&index);
197
198 return(index);
199 }
200
201 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
202
203 /**
204 * @} end of groupBayes group
205 */
206
207 #endif /* #if defined(ARM_FLOAT16_SUPPORTED) */
208
209