详情可以看原文:非线性函数的定点化快速实现 - 知乎 (zhihu.com)
在数值运算中,除基本的加减乘除运算外,还有其他许多非线性运算,如对数运算、开方运算、指数运算、三角函数运算等,实现这些非线性运算的方法一般有:
(1)调用编译系统的库函数; (2)查表法; (3)混合法;
对于系统实时性要求不高的,一般直接选择系统自带的库函数即可,但是如果运行在MCU等cortex-m系列或者单片机上时,此时平台的计算资源吃紧,如何在短时间内精确的计算出结果则显得非常重要。查表法固然可行,但是对精度要求较高时,空间占用会几句增加,所以实际应用中混合法最为常用。
对于像对数这样的非线性函数,输入值和函数值的变化范围都很大。如果输入值的变化范围很大,则作表就比较困难。而混合法可以比较好地解决这个问题,既不使表格太大,又能得到比较高的精度。本文仅以对数函数为例,如下可对其进行分解:
其中,
问题便化简为两个关键步骤:
1、制作 范围的表格,表格精度可以根据实际项目需求定夺;
2、将 x 分解;
在 C 语言中实现为:
int ln_fixed(unsigned int x, int c)
{
int rslt;
int s16Lable;
int s16Q = c;
x|= 1;
__ASM volatile ("CLZ %0,%1" : "=r"(s16Q) :"r"(x));
x= x<<s16Q;
s16Q += c;
x= x- 0x80000000L;
s16Lable = x>>22;
// LnTable 为精度为512的定标为16的表格
rslt = ((((int )(LnTable[s16Lable]) + (int )((31-s16Q)*0xB172L))>>6);
return rslt;
}
又例如,在 DSP 中对数值10000进行规格化的TMS320C25程序为:
LAC #10000
SACL TEMP
ZALH TEMP
LAR AR1,#0FH
RPT 14
NORM *-
上述程序执行后, AR1=#0eH, ACCH=2000(10进制)。
在 STM32H750硬件平台,为 Cortex-m7 版本,ARM-v7 架构,进行对比实验之后,将浮点转为定点之后,进行对数运算时最大速度差异可达3~4倍,且精度满足项目要求。