math_helper.c
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 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 * log10 (EnergySignal / 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 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 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 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 uint32_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 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 uint32_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 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 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 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 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 */ 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 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 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 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 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 472 #endif