blob: 356fbd5094048da80c3d1fbbd228c41e3bf45075 [file] [log] [blame]
/* ----------------------------------------------------------------------
* 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