Lookup Table and it‘s C#

Simulink Model:

Interpolation Method: Linear point-slope 线性点斜式 插值(就是常见的计算斜率插值)

Extrapolation Method: Clip

Index search method: Binary search (二分法搜索)   Linear search(线性搜索就是遍历搜索)

Code:

1. Binary search 和 Linear search 和 Linear point-slope 的代码基本例子

uint8_T look1_iu8lu32n24_binlcse(uint8_T u0, const uint8_T bp0[], const uint8_T table[], uint32_T maxIndex) 
//函数返回是最终插值计算的值
//UO 是需要被查找的x轴数值
//bp0 数组 是X 轴整个数组
//table 数组是 y 轴 的整个数组
//maxIndex 是X 轴的数组的元素数
{   
  uint32_T frac;  
  uint32_T iLeft = 0U;  
  uint32_T iRght = maxIndex;  
  uint8_T bpLeftVar;  
  uint8_T y;  
  
  // 二分查找 找到输入在的X轴的区间
//
  while (iRght - iLeft > 1U) {  
    frac = (iRght + iLeft) >> 1U;  //>>1u 等同于 /2
    if (u0 < bp0[frac]) {  
      iRght = frac;  
    } else {  
      iLeft = frac;  
    }  
  }  
//只要区间右侧-左侧大于1,则先取中间位置数,与目标值比较大小,确定中间位置被定为左边还是右边
//直到或者相邻的两个元素位置。
  
  // 计算分数值(如果u0在bp0范围内) 
//二分法只适用于单调增、减的数组
  if (u0 > bp0[0U] && u0 < bp0[maxIndex]) {  //目标值在x轴范围内
    bpLeftVar = bp0[iLeft];  
    frac = ((uint32_T)(uint8_T)((uint32_T)u0 - bpLeftVar) << 24) / (uint8_T)  
      ((uint32_T)bp0[iLeft + 1U] - bpLeftVar);  
  } //插值计算: 分子为 目标位置-左边  分母 右边-左边  得到占的比例。
//此处<<24  即*2^24可提高精度
else if (u0 <= bp0[0U]) {  
    frac = 0U;  
  } else {  
    frac = 16777216U; // 2^24  
  }  
  
  // 一维线性插值  
  bpLeftVar = table[iLeft + 1U];  
  uint8_T yL_0d0 = table[iLeft];  
  if (bpLeftVar >= yL_0d0) {  
    y = (uint8_T)(((uint32_T)(bpLeftVar - yL_0d0) * frac) >> 24) + yL_0d0;  
//比例有了那么就可计算y轴, 插值= (y右-y左)*比例+y左 注意上一步为提高精度<<24 最后要>>24 消除//掉
  } else {  
    y = yL_0d0 - (uint8_T)(((uint32_T)(yL_0d0 - bpLeftVar) * frac) >> 24);  
  }  
  
  return y;  //最终返回插值计算的y轴值
}

2. 现在看该模型Simulink 实际生成的code

A: 将X 轴 Y 轴进行数组化,1-D table 成为两个相同大小的数组

/* Definition for custom storage class: Global */
PRAGMA_MAPDATA const uint8_T Lookup1_X[5] = { 1U, 2U, 3U, 4U, 5U } ;
                                    /* Referenced by: '<S3>/1-D Lookup Table' */

PRAGMA_MAPDATA const uint8_T Lookup1_Y[5] = { 10U, 20U, 30U, 40U, 50U } ;
                                    /* Referenced by: '<S3>/1-D Lookup Table' */

PRAGMA_MAPDATA const uint8_T lookup2_X[5] = { 1U, 2U, 3U, 4U, 5U } ;
                                    /* Referenced by: '<S3>/2-D Lookup Table' */

PRAGMA_MAPDATA const uint8_T lookup2_Y[5] = { 10U, 20U, 30U, 40U, 50U } ;
                                    /* Referenced by: '<S3>/2-D Lookup Table' */

PRAGMA_MAPDATA const uint8_T lookup2_Z[25] = { 9U, 8U, 7U, 6U, 5U, 8U, 7U, 6U,
  5U, 4U, 7U, 6U, 5U, 4U, 3U, 6U, 5U, 4U, 3U, 2U, 5U, 4U, 3U, 2U, 1U } ;
                                    /* Referenced by: '<S3>/2-D Lookup Table' */

PRAGMA_MAPDATA const uint8_T lookuptableIN = 3U;/* Referenced by: '<S3>/Constant' */
PRAGMA_MAPDATA const uint8_T lookuptableIN2 = 5U;/* Referenced by: '<S3>/Constant1' */

 B-生成计算线性插值的回调函数

uint8_T look1_iu8lu32n24_binlcse(uint8_T u0, const uint8_T bp0[], const uint8_T
  table[], uint32_T maxIndex)
{
  uint32_T frac;
  uint32_T iLeft;
  uint32_T iRght;
  uint8_T bpLeftVar;
  uint8_T y;
  uint8_T yL_0d0;

  if (u0 <= bp0[0U]) {//如果目标小于X轴范围 那么fac=0,那么会得到X轴最小值对应的数

    iLeft = 0U;
    frac = 0U;
  } else if (u0 < bp0[maxIndex]) {//如果目标正常在X 范围,那么进行二分搜寻
    /* Binary Search */
    frac = maxIndex >> 1U; //取中
    iLeft = 0U;
    iRght = maxIndex;
    while (iRght - iLeft > 1U) {
      if (u0 < bp0[frac]) {
        iRght = frac;
      } else {
        iLeft = frac;
      }//重新限定范围

      frac = (iRght + iLeft) >> 1U;//更新取中,直到找到X轴相邻的两个元素的区间
    }

    bpLeftVar = bp0[iLeft];
    frac = ((uint32_T)(uint8_T)((uint32_T)u0 - bpLeftVar) << 24) / (uint8_T)
      ((uint32_T)bp0[iLeft + 1U] - bpLeftVar);
//计算 目标值在该区间内占得比例
  } else {//如果目标值大于X 轴范围 会得到x轴最大值对应的Y值
    iLeft = maxIndex - 1U;
    frac = 16777216U;
  }
//计算最终的插值 y
  bpLeftVar = table[iLeft + 1U];
  yL_0d0 = table[iLeft];//获得区间左右对应的y
  if (bpLeftVar >= yL_0d0) {//如果是增函数
    y = (uint8_T)((uint32_T)(uint8_T)(((uint8_T)((uint32_T)bpLeftVar - yL_0d0) *
      frac) >> 24) + yL_0d0);

  } else {//如果是减函数
    y = (uint8_T)((uint32_T)yL_0d0 - (uint8_T)(((uint8_T)((uint32_T)yL_0d0 -
      bpLeftVar) * frac) >> 24));
  }

  return y;
}

 C-调用插值计算函数。

  looktableOUT = (uint16_T)((uint32_T)((uint8_T)128U) * look1_iu8lu32n24_binlcse
    (lookuptableIN, (&(Lookup1_X[0])), (&(Lookup1_Y[0])), 4U));

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值