2024-05-13 08:14:17 +08:00

198 lines
6.0 KiB
C

/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _INTERP1D_H_
#define _INTERP1D_H_
/*! \brief Contains public interface to various functions related
* to the 1-D Linear Interpolation
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _Interp1d_PointType_
{
_iq x; /*!< x. */
_iq y; /*!< y. */
} Interp1d_PointType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief This is an linear interpolate calculation function using 2 x and the scale as input
* The result x should satisfy: scale = (x-x1) / (x2-x1)
*
* \param[in] x1 : x value of point 1
* \param[in] x2 : x value of point 2
* \param[in] scale : the scale = (x-x1) / (x2-x1)
* \return the value x in the scale equation
*/
static inline _iq Interp1d(_iq x1, _iq x2, _iq scale)
{
return (_IQmpy(scale, x2 - x1) + x1);
}
/*! \brief This is an linear interpolate calculation function using 2 points as input
* Calculate y for the given x, based on two points - (x1, y1) and (x2, y2)
*
* \note If x1 is equal to x2, which is not actually allowed, it will return
* (y1+y2)/2 instead. User should prevent this situation.
*
* \param[in] x1 : x value of point 1
* \param[in] y1 : y value of point 1
* \param[in] x2 : x value of point 2
* \param[in] y2 : y value of point 2
* \param[in] x : x value of the target point
* \return the y value of the target point
*/
static inline _iq Interp1dPoints(_iq x1, _iq y1, _iq x2, _iq y2, _iq x)
{
return (x2 != x1) ? (_IQmpy(_IQdiv(y2 - y1, x2 - x1), x - x1) + y1) : _IQdiv2(y2 + y1);
}
/*! \brief This is an linear interpolate calculation function using the whole table as input
*
* \note The values in x[] must be from smallest to biggest
*
* \param[in] u0 : x value of the target point
* \param[in] x[] : the x value array
* \param[in] y[] : the y value array
* \param[in] maxIndex : max index of the array
* \return the y value of the target point
*/
static inline _iq Interp1dTable(_iq u0, const _iq x[], const _iq y[], uint32_t maxIndex)
{
_iq frac;
uint32_t right;
uint32_t left;
uint32_t bpIdx;
if(u0 <= x[0U])
{
left = 0U;
frac = (x[1U] == x[0U]) ? _IQ(0.5) : _IQdiv(u0 - x[0U], x[1U] - x[0U]);
}
else if(u0 < x[maxIndex])
{
/* Binary Search */
bpIdx = maxIndex >> 1U;
left = 0U;
right = maxIndex;
while(right - left > 1U)
{
if(u0 < x[bpIdx])
{
right = bpIdx;
}
else
{
left = bpIdx;
}
bpIdx = (right + left) >> 1U;
}
frac = (x[left + 1U] != x[left]) ? _IQdiv(u0 - x[left], x[left + 1U] - x[left]) : _IQ(0.5);
}
else
{
left = maxIndex - 1U;
frac = (x[maxIndex] != x[maxIndex - 1U]) ? _IQdiv(u0 - x[maxIndex - 1U], x[maxIndex] - x[maxIndex - 1U]) : _IQ(0.5);
}
return (_IQmpy(_IQ(1.0) - frac, y[left]) + _IQmpy(y[left + 1U], frac));
}
/*! \brief This is an linear interpolate calculation function using the whole table as input
*
* \note The values in pPt[].x must be from smallest to biggest
*
* \param[in] u0 : x value of the target point
* \param[in] pPt : the pointer to the points array
* \param[in] maxIndex : max index of the array
* \return the y value of the target point
*/
static inline _iq Interp1dPtArray(_iq u0, const Interp1d_PointType *pPt, uint32_t maxIndex)
{
_iq frac;
uint32_t right;
uint32_t left;
uint32_t bpIdx;
if(u0 <= pPt[0U].x)
{
left = 0U;
frac = (pPt[1U].x == pPt[0U].x) ? _IQ(0.5) : _IQdiv(u0 - pPt[0U].x, pPt[1U].x - pPt[0U].x);
}
else if(u0 < pPt[maxIndex].x)
{
/* Binary Search */
bpIdx = maxIndex >> 1U;
left = 0U;
right = maxIndex;
while(right - left > 1U)
{
if(u0 < pPt[bpIdx].x)
{
right = bpIdx;
}
else
{
left = bpIdx;
}
bpIdx = (right + left) >> 1U;
}
frac = (pPt[left + 1U].x != pPt[left].x) ? _IQdiv(u0 - pPt[left].x, pPt[left + 1U].x - pPt[left].x) : _IQ(0.5);
}
else
{
left = maxIndex - 1U;
frac = (pPt[maxIndex].x != pPt[maxIndex - 1U].x) ? _IQdiv(u0 - pPt[maxIndex - 1U].x, pPt[maxIndex].x - pPt[maxIndex - 1U].x) : _IQ(0.5);
}
return (_IQmpy(_IQ(1.0) - frac, pPt[left].y) + _IQmpy(pPt[left + 1U].y, frac));
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _INTERP1D_H_ */