1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
3 *
4 * $Date: 17. January 2013
5 * $Revision: V1.4.0 b
6 *
7 * Project: CMSIS DSP Library
8 *
9 * Title: math_helper.c
10 *
11 * Description: Definition of all helper functions required.
12 *
13 * Target Processor: Cortex-M4/Cortex-M3
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * - Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * - Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 * - Neither the name of ARM LIMITED nor the names of its contributors
25 * may be used to endorse or promote products derived from this
26 * software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 * -------------------------------------------------------------------- */
41
42 /* ----------------------------------------------------------------------
43 * Include standard header files
44 * -------------------------------------------------------------------- */
45 #include<math.h>
46
47 /* ----------------------------------------------------------------------
48 * Include project header files
49 * -------------------------------------------------------------------- */
50 #include "math_helper.h"
51
52 /**
53 * @brief Caluclation of SNR
54 * @param[in] pRef Pointer to the reference buffer
55 * @param[in] pTest Pointer to the test buffer
56 * @param[in] buffSize total number of samples
57 * @return SNR
58 * The function Caluclates signal to noise ratio for the reference output
59 * and test output
60 */
61
arm_snr_f32(float * pRef,float * pTest,uint32_t buffSize)62 float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize)
63 {
64 float EnergySignal = 0.0, EnergyError = 0.0;
65 uint32_t i;
66 float SNR;
67 int temp;
68 int *test;
69
70 for (i = 0; i < buffSize; i++)
71 {
72 /* Checking for a NAN value in pRef array */
73 test = (int *)(&pRef[i]);
74 temp = *test;
75
76 if (temp == 0x7FC00000)
77 {
78 return(0);
79 }
80
81 /* Checking for a NAN value in pTest array */
82 test = (int *)(&pTest[i]);
83 temp = *test;
84
85 if (temp == 0x7FC00000)
86 {
87 return(0);
88 }
89 EnergySignal += pRef[i] * pRef[i];
90 EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
91 }
92
93 /* Checking for a NAN value in EnergyError */
94 test = (int *)(&EnergyError);
95 temp = *test;
96
97 if (temp == 0x7FC00000)
98 {
99 return(0);
100 }
101
102
103 SNR = 10 * (float32_t)log10 ((double)EnergySignal / (double)EnergyError);
104
105 return (SNR);
106
107 }
108
109
110 /**
111 * @brief Provide guard bits for Input buffer
112 * @param[in,out] input_buf Pointer to input buffer
113 * @param[in] blockSize block Size
114 * @param[in] guard_bits guard bits
115 * @return none
116 * The function Provides the guard bits for the buffer
117 * to avoid overflow
118 */
119
arm_provide_guard_bits_q15(q15_t * input_buf,uint32_t blockSize,uint32_t guard_bits)120 void arm_provide_guard_bits_q15 (q15_t * input_buf, uint32_t blockSize,
121 uint32_t guard_bits)
122 {
123 uint32_t i;
124
125 for (i = 0; i < blockSize; i++)
126 {
127 input_buf[i] = input_buf[i] >> guard_bits;
128 }
129 }
130
131 /**
132 * @brief Converts float to fixed in q12.20 format
133 * @param[in] pIn pointer to input buffer
134 * @param[out] pOut pointer to outputbuffer
135 * @param[in] numSamples number of samples in the input buffer
136 * @return none
137 * The function converts floating point values to fixed point(q12.20) values
138 */
139
arm_float_to_q12_20(float * pIn,q31_t * pOut,uint32_t numSamples)140 void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples)
141 {
142 uint32_t i;
143
144 for (i = 0; i < numSamples; i++)
145 {
146 /* 1048576.0f corresponds to pow(2, 20) */
147 pOut[i] = (q31_t) (pIn[i] * 1048576.0f);
148
149 pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
150
151 if (pIn[i] == (float) 1.0)
152 {
153 pOut[i] = 0x000FFFFF;
154 }
155 }
156 }
157
158 /**
159 * @brief Compare MATLAB Reference Output and ARM Test output
160 * @param[in] pIn Pointer to Ref buffer
161 * @param[in] pOut Pointer to Test buffer
162 * @param[in] numSamples number of samples in the buffer
163 * @return maximum difference
164 */
165
arm_compare_fixed_q15(q15_t * pIn,q15_t * pOut,uint32_t numSamples)166 uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t *pOut, uint32_t numSamples)
167 {
168 uint32_t i;
169 int32_t diff, diffCrnt = 0;
170 int32_t maxDiff = 0;
171
172 for (i = 0; i < numSamples; i++)
173 {
174 diff = pIn[i] - pOut[i];
175 diffCrnt = (diff > 0) ? diff : -diff;
176
177 if (diffCrnt > maxDiff)
178 {
179 maxDiff = diffCrnt;
180 }
181 }
182
183 return(maxDiff);
184 }
185
186 /**
187 * @brief Compare MATLAB Reference Output and ARM Test output
188 * @param[in] pIn Pointer to Ref buffer
189 * @param[in] pOut Pointer to Test buffer
190 * @param[in] numSamples number of samples in the buffer
191 * @return maximum difference
192 */
193
arm_compare_fixed_q31(q31_t * pIn,q31_t * pOut,uint32_t numSamples)194 uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t * pOut, uint32_t numSamples)
195 {
196 uint32_t i;
197 int32_t diff, diffCrnt = 0;
198 int32_t maxDiff = 0;
199
200 for (i = 0; i < numSamples; i++)
201 {
202 diff = pIn[i] - pOut[i];
203 diffCrnt = (diff > 0) ? diff : -diff;
204
205 if (diffCrnt > maxDiff)
206 {
207 maxDiff = diffCrnt;
208 }
209 }
210
211 return(maxDiff);
212 }
213
214 /**
215 * @brief Provide guard bits for Input buffer
216 * @param[in,out] input_buf Pointer to input buffer
217 * @param[in] blockSize block Size
218 * @param[in] guard_bits guard bits
219 * @return none
220 * The function Provides the guard bits for the buffer
221 * to avoid overflow
222 */
223
arm_provide_guard_bits_q31(q31_t * input_buf,uint32_t blockSize,uint32_t guard_bits)224 void arm_provide_guard_bits_q31 (q31_t * input_buf,
225 uint32_t blockSize,
226 uint32_t guard_bits)
227 {
228 uint32_t i;
229
230 for (i = 0; i < blockSize; i++)
231 {
232 input_buf[i] = input_buf[i] >> guard_bits;
233 }
234 }
235
236 /**
237 * @brief Provide guard bits for Input buffer
238 * @param[in,out] input_buf Pointer to input buffer
239 * @param[in] blockSize block Size
240 * @param[in] guard_bits guard bits
241 * @return none
242 * The function Provides the guard bits for the buffer
243 * to avoid overflow
244 */
245
arm_provide_guard_bits_q7(q7_t * input_buf,uint32_t blockSize,uint32_t guard_bits)246 void arm_provide_guard_bits_q7 (q7_t * input_buf,
247 uint32_t blockSize,
248 uint32_t guard_bits)
249 {
250 uint32_t i;
251
252 for (i = 0; i < blockSize; i++)
253 {
254 input_buf[i] = input_buf[i] >> guard_bits;
255 }
256 }
257
258
259
260 /**
261 * @brief Caluclates number of guard bits
262 * @param[in] num_adds number of additions
263 * @return guard bits
264 * The function Caluclates the number of guard bits
265 * depending on the numtaps
266 */
267
arm_calc_guard_bits(uint32_t num_adds)268 uint32_t arm_calc_guard_bits (uint32_t num_adds)
269 {
270 uint32_t i = 1, j = 0;
271
272 if (num_adds == 1)
273 {
274 return (0);
275 }
276
277 while (i < num_adds)
278 {
279 i = i * 2;
280 j++;
281 }
282
283 return (j);
284 }
285
286 /**
287 * @brief Apply guard bits to buffer
288 * @param[in,out] pIn pointer to input buffer
289 * @param[in] numSamples number of samples in the input buffer
290 * @param[in] guard_bits guard bits
291 * @return none
292 */
293
arm_apply_guard_bits(float32_t * pIn,uint32_t numSamples,uint32_t guard_bits)294 void arm_apply_guard_bits (float32_t *pIn,
295 uint32_t numSamples,
296 uint32_t guard_bits)
297 {
298 uint32_t i;
299
300 for (i = 0; i < numSamples; i++)
301 {
302 pIn[i] = pIn[i] * arm_calc_2pow(guard_bits);
303 }
304 }
305
306 /**
307 * @brief Calculates pow(2, numShifts)
308 * @param[in] numShifts number of shifts
309 * @return pow(2, numShifts)
310 */
arm_calc_2pow(uint32_t numShifts)311 uint32_t arm_calc_2pow(uint32_t numShifts)
312 {
313
314 uint32_t i, val = 1;
315
316 for (i = 0; i < numShifts; i++)
317 {
318 val = val * 2;
319 }
320
321 return(val);
322 }
323
324
325
326 /**
327 * @brief Converts float to fixed q14
328 * @param[in] pIn pointer to input buffer
329 * @param[out] pOut pointer to output buffer
330 * @param[in] numSamples number of samples in the buffer
331 * @return none
332 * The function converts floating point values to fixed point values
333 */
334
arm_float_to_q14(float * pIn,q15_t * pOut,uint32_t numSamples)335 void arm_float_to_q14 (float *pIn, q15_t *pOut, uint32_t numSamples)
336 {
337 uint32_t i;
338
339 for (i = 0; i < numSamples; i++)
340 {
341 /* 16384.0f corresponds to pow(2, 14) */
342 pOut[i] = (q15_t) (pIn[i] * 16384.0f);
343
344 pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
345
346 if (pIn[i] == (float) 2.0)
347 {
348 pOut[i] = 0x7FFF;
349 }
350
351 }
352
353 }
354
355
356 /**
357 * @brief Converts float to fixed q30 format
358 * @param[in] pIn pointer to input buffer
359 * @param[out] pOut pointer to output buffer
360 * @param[in] numSamples number of samples in the buffer
361 * @return none
362 * The function converts floating point values to fixed point values
363 */
364
arm_float_to_q30(float * pIn,q31_t * pOut,uint32_t numSamples)365 void arm_float_to_q30 (float *pIn, q31_t * pOut, uint32_t numSamples)
366 {
367 uint32_t i;
368
369 for (i = 0; i < numSamples; i++)
370 {
371 /* 1073741824.0f corresponds to pow(2, 30) */
372 pOut[i] = (q31_t) (pIn[i] * 1073741824.0f);
373
374 pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
375
376 if (pIn[i] == (float) 2.0)
377 {
378 pOut[i] = 0x7FFFFFFF;
379 }
380 }
381 }
382
383 /**
384 * @brief Converts float to fixed q30 format
385 * @param[in] pIn pointer to input buffer
386 * @param[out] pOut pointer to output buffer
387 * @param[in] numSamples number of samples in the buffer
388 * @return none
389 * The function converts floating point values to fixed point values
390 */
391
arm_float_to_q29(float * pIn,q31_t * pOut,uint32_t numSamples)392 void arm_float_to_q29 (float *pIn, q31_t *pOut, uint32_t numSamples)
393 {
394 uint32_t i;
395
396 for (i = 0; i < numSamples; i++)
397 {
398 /* 1073741824.0f corresponds to pow(2, 30) */
399 pOut[i] = (q31_t) (pIn[i] * 536870912.0f);
400
401 pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
402
403 if (pIn[i] == (float) 4.0)
404 {
405 pOut[i] = 0x7FFFFFFF;
406 }
407 }
408 }
409
410
411 /**
412 * @brief Converts float to fixed q28 format
413 * @param[in] pIn pointer to input buffer
414 * @param[out] pOut pointer to output buffer
415 * @param[in] numSamples number of samples in the buffer
416 * @return none
417 * The function converts floating point values to fixed point values
418 */
419
arm_float_to_q28(float * pIn,q31_t * pOut,uint32_t numSamples)420 void arm_float_to_q28 (float *pIn, q31_t *pOut, uint32_t numSamples)
421 {
422 uint32_t i;
423
424 for (i = 0; i < numSamples; i++)
425 {
426 /* 268435456.0f corresponds to pow(2, 28) */
427 pOut[i] = (q31_t) (pIn[i] * 268435456.0f);
428
429 pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
430
431 if (pIn[i] == (float) 8.0)
432 {
433 pOut[i] = 0x7FFFFFFF;
434 }
435 }
436 }
437
438 /*
439
440 Conflicting with the new clip functions in CMSIS-DSP and not used
441 in the examples.
442
443 */
444 #if 0
445 /**
446 * @brief Clip the float values to +/- 1
447 * @param[in,out] pIn input buffer
448 * @param[in] numSamples number of samples in the buffer
449 * @return none
450 * The function converts floating point values to fixed point values
451 */
452
453 void arm_clip_f32 (float *pIn, uint32_t numSamples)
454 {
455 uint32_t i;
456
457 for (i = 0; i < numSamples; i++)
458 {
459 if (pIn[i] > 1.0f)
460 {
461 pIn[i] = 1.0;
462 }
463 else if ( pIn[i] < -1.0f)
464 {
465 pIn[i] = -1.0;
466 }
467
468 }
469 }
470
471 #endif
472
473