本质上,我试图使用在下面的代码中计算出来的值,但是当我将值存储在所有具有自己速率的对象中时,只会添加足够多的字节,从而导致缓存丢失。显然,使用查找表无助于解决问题。
所以我正在寻找一种方法,比标准的幂函数更快地得到这些值,由于可能的输入是非常有限的,我是否可以使用任何技巧?
static inline
double __attribute(( pure )) get_decay_rate(uint8_t rate)
{
if(rate >= 128)
{
return 65535.0/65536.0;
}
double k = pow(2, rate/8.0);
return (k - 1.0) / k;
}
/* pseudocode:
double k = (int) pow(2, k/8.0);
k = (k - 1) / k;
return log(65535/65536)/log(k);
*/
static inline
uint16_t __attribute(( pure )) get_decay_modulus(uint8_t rate)
{
if(rate <= 128)
{
return 1;
}
//turns out to be the same as the above pseudocode, for some reason.
return pow(2, (rate - 128) / 8.0);
}发布于 2016-07-31 04:16:46
走这条线:
double k = pow(2, rate/8.0);基本上,你在这里所做的是将2提高到一个不动点数的幂。
您可以利用以下事实: pow(a,b+c) = pow(a,b) * pow(a,c),非整数数=整数部分+小数部分。所以你用不动点数的积分部分来计算pow,然后用分数部分的pow乘以它。
将8个小数指数存储在查找表中:
double fractionalPowersOf2[8];
for(int i = 0; i < 8; i++)
fractionalPowersOf2[i] = pow(2.0, i / 8.0);然后你可以这样计算:
double k = (double)(1 << (rate >> 3)) * fractionalPowersOf2[rate & 7];这掩盖了小数部分,并将其用于表查找,然后使用位移位将2乘以整数的幂。如果转换为double太慢,您也可以使用查找表。
您还可以使用一些奇特的位魔术类型方法,通过转换指针等方法,将值作为双值的指数使用,但这是不可移植的。
编辑:正如user3386109在注释中指出的那样,如果打开优化,编译器可能会为您优化将2提升到整数值的能力,因此这段代码可能会更快:
double k = pow(2,rate>>3) * table[rate&7];https://stackoverflow.com/questions/38680065
复制相似问题