text: /* ----------------------------------------------------------------------
   * Copyright (C) 2010 ARM Limited. All rights reserved.
   *
   * $Date:        29. November 2010
   * $Revision:    V1.0.3
   *
   * Project:      CMSIS DSP Library
   *
   * Title:        math_helper.h
   *
   *
   * Description:	Prototypes of all helper functions required.
   *
   * Target Processor: Cortex-M4/Cortex-M3
   *
   * Version 1.0.3 2010/11/29
   *    Re-organized the CMSIS folders and updated documentation.
   *
   * Version 1.0.2 2010/11/11
   *    Documentation updated.
   *
   * Version 1.0.1 2010/10/05
   *    Production release and review comments incorporated.
   *
   * Version 1.0.0 2010/09/20
   *    Production release and review comments incorporated.
   *
   * Version 0.0.7  2010/06/10
   *    Misra-C changes done
   * -------------------------------------------------------------------- */
  
  /*
   * This file was imported from the ARM CMSIS-DSP library test suite and
   * reworked for use in the Zephyr tests.
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  
  #ifndef MATH_HELPER_H
  #define MATH_HELPER_H
  
  #include <arm_math.h>
  #ifdef CONFIG_CMSIS_DSP_FLOAT16
  #include <arm_math_f16.h>
  #endif
  
  /**
   * @brief  Calculation of SNR
   * @param  float*   Pointer to the reference buffer
   * @param  float*   Pointer to the test buffer
   * @param  uint32_t    total number of samples
   * @return float    SNR
   * The function calculates signal to noise ratio for the reference output
   * and test output
   */
  
  /* If NaN, force SNR to 0.0 to ensure test will fail */
  #define IFNANRETURNZERO(val)		\
  	do {				\
  		if (isnan((val))) {	\
  			return 0.0;	\
  		}			\
  	} while (0)
  
  #define IFINFINITERETURN(val, def)		\
  	do {					\
  		if (isinf((val))) {		\
  			if ((val) > 0) {	\
  				return def;	\
  			} else {		\
  				return -def;	\
  			}			\
  		}				\
  	} while (0)
  
  static inline double arm_snr_f64(const double *pRef, const double *pTest,
  	uint32_t buffSize)
  {
  	double EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	double SNR;
  
  	for (i = 0; i < buffSize; i++) {
  		/* Checking for a NAN value in pRef array */
  		IFNANRETURNZERO(pRef[i]);
  
  		/* Checking for a NAN value in pTest array */
  		IFNANRETURNZERO(pTest[i]);
  
  		EnergySignal += pRef[i] * pRef[i];
  		EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
  	}
  
  	/* Checking for a NAN value in EnergyError */
  	IFNANRETURNZERO(EnergyError);
  
  	SNR = 10 * log10(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  static inline float arm_snr_f32(const float *pRef, const float *pTest,
  	uint32_t buffSize)
  {
  	float EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	for (i = 0; i < buffSize; i++) {
  		/* Checking for a NAN value in pRef array */
  		IFNANRETURNZERO(pRef[i]);
  
  		/* Checking for a NAN value in pTest array */
  		IFNANRETURNZERO(pTest[i]);
  
  		EnergySignal += pRef[i] * pRef[i];
  		EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
  	}
  
  	/* Checking for a NAN value in EnergyError */
  	IFNANRETURNZERO(EnergyError);
  
  
  	SNR = 10 * log10f(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  #ifdef CONFIG_CMSIS_DSP_FLOAT16
  static inline float arm_snr_f16(const float16_t *pRef, const float16_t *pTest,
  	uint32_t buffSize)
  {
  	float EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	for (i = 0; i < buffSize; i++) {
  		/* Checking for a NAN value in pRef array */
  		IFNANRETURNZERO((float)pRef[i]);
  
  		/* Checking for a NAN value in pTest array */
  		IFNANRETURNZERO((float)pTest[i]);
  
  		EnergySignal += pRef[i] * pRef[i];
  		EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
  	}
  
  	/* Checking for a NAN value in EnergyError */
  	IFNANRETURNZERO(EnergyError);
  
  
  	SNR = 10 * log10f(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  #endif /* CONFIG_CMSIS_DSP_FLOAT16 */
  
  static inline float arm_snr_q63(const q63_t *pRef, const q63_t *pTest,
  	uint32_t buffSize)
  {
  	double EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	double testVal, refVal;
  
  	for (i = 0; i < buffSize; i++) {
  		testVal = ((double)pTest[i]) / 9223372036854775808.0;
  		refVal = ((double)pRef[i]) / 9223372036854775808.0;
  
  		EnergySignal += refVal * refVal;
  		EnergyError += (refVal - testVal) * (refVal - testVal);
  	}
  
  
  	SNR = 10 * log10(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  static inline float arm_snr_q31(const q31_t *pRef, const q31_t *pTest,
  	uint32_t buffSize)
  {
  	float EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	float32_t testVal, refVal;
  
  	for (i = 0; i < buffSize; i++) {
  
  		testVal = ((float32_t)pTest[i]) / 2147483648.0f;
  		refVal = ((float32_t)pRef[i]) / 2147483648.0f;
  
  		EnergySignal += refVal * refVal;
  		EnergyError += (refVal - testVal) * (refVal - testVal);
  	}
  
  
  	SNR = 10 * log10f(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  static inline float arm_snr_q15(const q15_t *pRef, const q15_t *pTest,
  	uint32_t buffSize)
  {
  	float EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	float32_t testVal, refVal;
  
  	for (i = 0; i < buffSize; i++) {
  		testVal = ((float32_t)pTest[i]) / 32768.0f;
  		refVal = ((float32_t)pRef[i]) / 32768.0f;
  
  		EnergySignal += refVal * refVal;
  		EnergyError += (refVal - testVal) * (refVal - testVal);
  	}
  
  	SNR = 10 * log10f(EnergySignal / EnergyError);
  
  	/* Checking for a NAN value in SNR */
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  static inline float arm_snr_q7(const q7_t *pRef, const q7_t *pTest,
  	uint32_t buffSize)
  {
  	float EnergySignal = 0.0, EnergyError = 0.0;
  	uint32_t i;
  	float SNR;
  
  	float32_t testVal, refVal;
  
  	for (i = 0; i < buffSize; i++) {
  		testVal = ((float32_t)pTest[i]) / 128.0f;
  		refVal = ((float32_t)pRef[i]) / 128.0f;
  
  		EnergySignal += refVal * refVal;
  		EnergyError += (refVal - testVal) * (refVal - testVal);
  	}
  
  	SNR = 10 * log10f(EnergySignal / EnergyError);
  
  	IFNANRETURNZERO(SNR);
  	IFINFINITERETURN(SNR, 100000.0);
  
  	return SNR;
  }
  
  #endif
  