関数の速度(11)

前回のは[-π/2,π/2]で成り立っていたが、
実数全域でも成り立つようにしよう。
素直に書くと、


double sin2(double x) {
int i = (int)(x * (1 / M_PI) + 0.5);
if(x < -M_PI / 2)
i--;
if(i & 1)
x = i * M_PI - x;
else
x = x - i * M_PI;
double x2 = x * x;
return x * ((((1.0 / 362880 * x2 - 1.0 / 5040) * x2
+ 1.0 / 120) * x2 - 1.0 / 6) * x2 + 1);
}

これで48ns→31ns。
このコードは、intへのキャストが非常に遅い。
VC2003だとPentium4コンパイラオプション(/G7だっけ?)をつけると速くなったが、VC2005では見当たらない。
ほとんど[-π,π]でしか使わないので、
そこだけ速くして、あとは犠牲になってもらおう。


double sin3(double x) {
double y = abs(x);
if(M_PI / 2 < y) {
if(0 < x) {
if(x <= M_PI * 3 / 2) {
x = M_PI - x;
}
else {
int i = (int)(x * (1 / M_PI) + 0.5);
if(i & 1)
x = i * M_PI - x;
else
x = x - i * M_PI;
}
}
else {
if(-3 * M_PI / 2 <= x) {
x = -M_PI - x;
}
else {
int i = (int)(x * (1 / M_PI) - 0.5);
if(i & 1)
x = i * M_PI - x;
else
x = x - i * M_PI;
}
}
}
double x2 = x * x;
return x * ((((1.0 / 362880 * x2 - 1.0 / 5040) * x2
+ 1.0 / 120) * x2 - 1.0 / 6) * x2 + 1);
}

これで、21ns。