C语言高速数学库
引子
如果游戏圈最近有什么大新闻,那一定就是switch被破解了,而且是被破解连底裤都不剩,简直可怜。我个人不太鼓励普通玩家破解,但是也得承认,我个人对于自制软件和老金一直有很大兴趣。为了体验ns自制软件软件开发,我个人甚至专门另外购置一台ns研究。
要说ns的破解,就不得不提到34c3大会(第34届欧洲黑客联盟大会,Chaos Computer Club)。在大会上,Plutoo、Derrek、Naehrwert三位大神对switch内核权限漏洞的利用技巧进行了展示。
34c3大会上还展示了一个名为34c3-demo的demo,之后,homebrew(自制软件)便一日千里。而本文的主题,就藏在34c3-demo之中。
34c3-demo给出了求二为底的指数函数,二为底的对数函数,三角函数,x的y次方这样常用函数的实现。时间复杂度均为 O(1)。
fast_exp2
#define _BIT(n) (1<<(n))
float fast_exp2(float x)
{
union { uint32_t i; float f; } v;
float offset = (x < 0) ? 1.0f : 0.0f;
float clipp = (x < -126) ? -126.0f : x;
int w = clipp;
float z = clipp - w + offset;
v.i = (uint32_t)(_BIT(23) * (clipp + 121.2740575f + 27.7280233f / (4.84252568f - z) - 1.49012907f * z));
return v.f;
}
fast_log2
float fast_log2(float x)
{
union { float f; uint32_t i; } vx;
union { uint32_t i; float f; } mx;
vx.f = x;
mx.i = (vx.i & 0x007FFFFF) | 0x3F000000;
float y = vx.i;
y *= 1.1920928955078125e-7f;
return y - 124.22551499f - 1.498030302f * mx.f - 1.72587999f / (0.3520887068f + mx.f);
}
fast_sinf & fast_cosf
#define M_TAU (2*M_PI)
float fast_cosc(float x)
{
x -= 0.25f + floorf(x + 0.25f);
x *= 16.0f * (fabs(x) - 0.5f);
x += 0.225f * x * (fabs(x) - 1.0f);
return x;
}
float fast_sinf(float x)
{
return fast_cosc(x/M_TAU - 0.25f);
}
float fast_cosf(float x)
{
return fast_cosc(x/M_TAU);
}
fast_powf
float fast_powf(float base, float exponent)
{
return fast_exp2(fast_log2(base)*exponent);
}
faster math
上面的对float特化函数已经够快了(时间复杂度为O(1)),但是,如果我还嫌慢,怎么办。那就要借助SIMD了。fastapprox项目提供了如下函数的近似向量化实现:
- exponential, logarithm, and power
- lgamma and digamma
- cosh, sinh, tanh
- cos, sin, tan
- sigmoid and erf
- Lambert W
Comments