1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010 ARM Limited. All rights reserved.
3 *
4 * $Date: 29. November 2010
5 * $Revision: V1.0.3
6 *
7 * Project: CMSIS DSP Library
8 *
9 * Title: math_helper.h
10 *
11 *
12 * Description: Prototypes of all helper functions required.
13 *
14 * Target Processor: Cortex-M4/Cortex-M3
15 *
16 * Version 1.0.3 2010/11/29
17 * Re-organized the CMSIS folders and updated documentation.
18 *
19 * Version 1.0.2 2010/11/11
20 * Documentation updated.
21 *
22 * Version 1.0.1 2010/10/05
23 * Production release and review comments incorporated.
24 *
25 * Version 1.0.0 2010/09/20
26 * Production release and review comments incorporated.
27 *
28 * Version 0.0.7 2010/06/10
29 * Misra-C changes done
30 * -------------------------------------------------------------------- */
31
32 /*
33 * This file was imported from the ARM CMSIS-DSP library test suite and
34 * reworked for use in the Zephyr tests.
35 *
36 * SPDX-License-Identifier: Apache-2.0
37 */
38
39 #ifndef MATH_HELPER_H
40 #define MATH_HELPER_H
41
42 #include <arm_math.h>
43 #ifdef CONFIG_CMSIS_DSP_FLOAT16
44 #include <arm_math_f16.h>
45 #endif
46
47 /**
48 * @brief Calculation of SNR
49 * @param float* Pointer to the reference buffer
50 * @param float* Pointer to the test buffer
51 * @param uint32_t total number of samples
52 * @return float SNR
53 * The function calculates signal to noise ratio for the reference output
54 * and test output
55 */
56
57 /* If NaN, force SNR to 0.0 to ensure test will fail */
58 #define IFNANRETURNZERO(val) \
59 do { \
60 if (isnan((val))) { \
61 return 0.0; \
62 } \
63 } while (0)
64
65 #define IFINFINITERETURN(val, def) \
66 do { \
67 if (isinf((val))) { \
68 if ((val) > 0) { \
69 return def; \
70 } else { \
71 return -def; \
72 } \
73 } \
74 } while (0)
75
arm_snr_f64(const double * pRef,const double * pTest,uint32_t buffSize)76 static inline double arm_snr_f64(const double *pRef, const double *pTest,
77 uint32_t buffSize)
78 {
79 double EnergySignal = 0.0, EnergyError = 0.0;
80 uint32_t i;
81 double SNR;
82
83 for (i = 0; i < buffSize; i++) {
84 /* Checking for a NAN value in pRef array */
85 IFNANRETURNZERO(pRef[i]);
86
87 /* Checking for a NAN value in pTest array */
88 IFNANRETURNZERO(pTest[i]);
89
90 EnergySignal += pRef[i] * pRef[i];
91 EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
92 }
93
94 /* Checking for a NAN value in EnergyError */
95 IFNANRETURNZERO(EnergyError);
96
97 SNR = 10 * log10(EnergySignal / EnergyError);
98
99 /* Checking for a NAN value in SNR */
100 IFNANRETURNZERO(SNR);
101 IFINFINITERETURN(SNR, 100000.0);
102
103 return SNR;
104 }
105
arm_snr_f32(const float * pRef,const float * pTest,uint32_t buffSize)106 static inline float arm_snr_f32(const float *pRef, const float *pTest,
107 uint32_t buffSize)
108 {
109 float EnergySignal = 0.0, EnergyError = 0.0;
110 uint32_t i;
111 float SNR;
112
113 for (i = 0; i < buffSize; i++) {
114 /* Checking for a NAN value in pRef array */
115 IFNANRETURNZERO(pRef[i]);
116
117 /* Checking for a NAN value in pTest array */
118 IFNANRETURNZERO(pTest[i]);
119
120 EnergySignal += pRef[i] * pRef[i];
121 EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
122 }
123
124 /* Checking for a NAN value in EnergyError */
125 IFNANRETURNZERO(EnergyError);
126
127
128 SNR = 10 * log10f(EnergySignal / EnergyError);
129
130 /* Checking for a NAN value in SNR */
131 IFNANRETURNZERO(SNR);
132 IFINFINITERETURN(SNR, 100000.0);
133
134 return SNR;
135 }
136
137 #ifdef CONFIG_CMSIS_DSP_FLOAT16
arm_snr_f16(const float16_t * pRef,const float16_t * pTest,uint32_t buffSize)138 static inline float arm_snr_f16(const float16_t *pRef, const float16_t *pTest,
139 uint32_t buffSize)
140 {
141 float EnergySignal = 0.0, EnergyError = 0.0;
142 uint32_t i;
143 float SNR;
144
145 for (i = 0; i < buffSize; i++) {
146 /* Checking for a NAN value in pRef array */
147 IFNANRETURNZERO((float)pRef[i]);
148
149 /* Checking for a NAN value in pTest array */
150 IFNANRETURNZERO((float)pTest[i]);
151
152 EnergySignal += pRef[i] * pRef[i];
153 EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
154 }
155
156 /* Checking for a NAN value in EnergyError */
157 IFNANRETURNZERO(EnergyError);
158
159
160 SNR = 10 * log10f(EnergySignal / EnergyError);
161
162 /* Checking for a NAN value in SNR */
163 IFNANRETURNZERO(SNR);
164 IFINFINITERETURN(SNR, 100000.0);
165
166 return SNR;
167 }
168 #endif /* CONFIG_CMSIS_DSP_FLOAT16 */
169
arm_snr_q63(const q63_t * pRef,const q63_t * pTest,uint32_t buffSize)170 static inline float arm_snr_q63(const q63_t *pRef, const q63_t *pTest,
171 uint32_t buffSize)
172 {
173 double EnergySignal = 0.0, EnergyError = 0.0;
174 uint32_t i;
175 float SNR;
176
177 double testVal, refVal;
178
179 for (i = 0; i < buffSize; i++) {
180 testVal = ((double)pTest[i]) / 9223372036854775808.0;
181 refVal = ((double)pRef[i]) / 9223372036854775808.0;
182
183 EnergySignal += refVal * refVal;
184 EnergyError += (refVal - testVal) * (refVal - testVal);
185 }
186
187
188 SNR = 10 * log10(EnergySignal / EnergyError);
189
190 /* Checking for a NAN value in SNR */
191 IFNANRETURNZERO(SNR);
192 IFINFINITERETURN(SNR, 100000.0);
193
194 return SNR;
195 }
196
arm_snr_q31(const q31_t * pRef,const q31_t * pTest,uint32_t buffSize)197 static inline float arm_snr_q31(const q31_t *pRef, const q31_t *pTest,
198 uint32_t buffSize)
199 {
200 float EnergySignal = 0.0, EnergyError = 0.0;
201 uint32_t i;
202 float SNR;
203
204 float32_t testVal, refVal;
205
206 for (i = 0; i < buffSize; i++) {
207
208 testVal = ((float32_t)pTest[i]) / 2147483648.0f;
209 refVal = ((float32_t)pRef[i]) / 2147483648.0f;
210
211 EnergySignal += refVal * refVal;
212 EnergyError += (refVal - testVal) * (refVal - testVal);
213 }
214
215
216 SNR = 10 * log10f(EnergySignal / EnergyError);
217
218 /* Checking for a NAN value in SNR */
219 IFNANRETURNZERO(SNR);
220 IFINFINITERETURN(SNR, 100000.0);
221
222 return SNR;
223 }
224
arm_snr_q15(const q15_t * pRef,const q15_t * pTest,uint32_t buffSize)225 static inline float arm_snr_q15(const q15_t *pRef, const q15_t *pTest,
226 uint32_t buffSize)
227 {
228 float EnergySignal = 0.0, EnergyError = 0.0;
229 uint32_t i;
230 float SNR;
231
232 float32_t testVal, refVal;
233
234 for (i = 0; i < buffSize; i++) {
235 testVal = ((float32_t)pTest[i]) / 32768.0f;
236 refVal = ((float32_t)pRef[i]) / 32768.0f;
237
238 EnergySignal += refVal * refVal;
239 EnergyError += (refVal - testVal) * (refVal - testVal);
240 }
241
242 SNR = 10 * log10f(EnergySignal / EnergyError);
243
244 /* Checking for a NAN value in SNR */
245 IFNANRETURNZERO(SNR);
246 IFINFINITERETURN(SNR, 100000.0);
247
248 return SNR;
249 }
250
arm_snr_q7(const q7_t * pRef,const q7_t * pTest,uint32_t buffSize)251 static inline float arm_snr_q7(const q7_t *pRef, const q7_t *pTest,
252 uint32_t buffSize)
253 {
254 float EnergySignal = 0.0, EnergyError = 0.0;
255 uint32_t i;
256 float SNR;
257
258 float32_t testVal, refVal;
259
260 for (i = 0; i < buffSize; i++) {
261 testVal = ((float32_t)pTest[i]) / 128.0f;
262 refVal = ((float32_t)pRef[i]) / 128.0f;
263
264 EnergySignal += refVal * refVal;
265 EnergyError += (refVal - testVal) * (refVal - testVal);
266 }
267
268 SNR = 10 * log10f(EnergySignal / EnergyError);
269
270 IFNANRETURNZERO(SNR);
271 IFINFINITERETURN(SNR, 100000.0);
272
273 return SNR;
274 }
275
276 #endif
277