快速FloatSin函数
就是一个快速实现求 float 的 Sin 函数。
#ifdef _MSC_VER
typedef __int32 int32_t;
#else
#include <stdint.h>
#endif
inline int32_t fast_round(double x) {
#ifndef NO_FAST_TRUNCATE
const double MAGIC_ROUND = 6755399441055744.0; /* https://stereopsis.com/sree/fpu2006.html */
union {
double d;
struct {
#ifdef BIG_ENDIAN
int32_t hw;
int32_t lw;
#else
int32_t lw;
int32_t hw;
#endif
};
} fast_trunc;
fast_trunc.d = x;
fast_trunc.d += MAGIC_ROUND;
return fast_trunc.lw;
#else
if (x < 0) {
return (int32_t)(x - 0.5);
}
else {
return (int32_t)(x + 0.5);
}
#endif
}
const double PI = 3.14159265358979323846264338327950288;
const double INVPI = 0.31830988618379067153776752674502872;
const double A = 0.00735246819687011731341356165096815;
const double B = -0.16528911397014738207016302002888890;
const double C = 0.99969198629596757779830113868360584;
// sin 516ms
// fast_sin1 257ms
// 有部分误差
inline double fast_sin1(double x) {
int32_t k;
double x2;
// 查询 x 在[PI/2, -PI/2] 的偏移
k = fast_round(INVPI * x);
// 调整 x 进入[PI/2, -PI/2]
x -= k * PI;
// 计算sin
x2 = x * x;
x = x*(C + x2*(B + A*x2));
// 纠正负值
if (k % 2) x = -x;
return x;
}
//泰勒函数逼近
//查表法的误差如下
// 91 x 2 bytes ==> 182 bytes
unsigned int isinTable16[] = {
0, 1144, 2287, 3430, 4571, 5712, 6850, 7987, 9121, 10252, 11380,
12505, 13625, 14742, 15854, 16962, 18064, 19161, 20251, 21336, 22414,
23486, 24550, 25607, 26655, 27696, 28729, 29752, 30767, 31772, 32768,
33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243, 42125,
42995, 43851, 44695, 45524, 46340, 47142, 47929, 48702, 49460, 50203,
50930, 51642, 52339, 53019, 53683, 54331, 54962, 55577, 56174, 56755,
57318, 57864, 58392, 58902, 59395, 59869, 60325, 60763, 61182, 61583,
61965, 62327, 62671, 62996, 63302, 63588, 63855, 64103, 64331, 64539,
64728, 64897, 65047, 65176, 65286, 65375, 65445, 65495, 65525, 65535,
};
float fast_sin4(float f)
{
long x = f + 0.5;
bool pos = true;
if (x < 0)
{
x = -x;
pos = !pos;
}
if (x >= 360) x %= 360;
if (x > 180)
{
x -= 180;
pos = !pos;
}
if (x > 90) x = 180 - x;;
if (pos) return isinTable16[x] * 0.0000152590219; // 1/65535.0
return isinTable16[x] * -0.0000152590219;
}