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