引子

       如果游戏圈最近有什么大新闻,那一定就是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项目提供了如下函数的近似向量化实现: