、およびのポイント(a,b)
が与えられた場合、それは 45 度または 0 度に近いですか?a<b
a>=0
b>=0
ええと、tan(theta) = opposite/adjacent
そして 0 度から 45 度の範囲で、tan は単調に増加しています。
tan(22.5 degrees) =~ 207107/500000
. したがって、 の場合a/b > 207107/500000
、最も近い角度は 45 度です。の場合a/b < 207107/500000
、最も近い角度は0
度です。と言って、浮動小数点演算を使わなくてもこれを行うことができます500000*a < 207107*b
。
任意の点 について(a,b)
は、a と b の記号を介して、それがどの象限にあるかを把握できます。問題を (否定によって) 正-正の象限に回転させ、結果の角度でその回転を反転させることができます (これは非常に単純なマップです)。
(a,b)
正正象限の任意の場合a>b
、aとbを逆にするだけで上記のように解けば、「0度に近い」は「90度に近い」に相当します。
上記のいくつかは過度に分岐していますが、これらの分岐を整数演算に変換し、配列アクセスで終了できるはずです。
ここで、一部のシステムでは、三角関数の組み込みが非常に高速であり、分岐のない整数演算と配列ルックアップの山よりもはるかに高速であることに注意してください。最初のステップはarctan
、より高速なに置き換えることができるかどうかを確認することですarctan
。
bool neg_a = a<0;
bool neg_b = b<0;
a *= (1-2*neg_a);
b *= (1-2*neg_b);
bool near_0 = 500000*a<207107*b; // a/b < 207107/500000
bool near_90 = 207107*a>500000*b; // a/b > 500000/207107
bool near_45 = !near_0 & !near_90;
// 3 CW 2 1
// -+ | ++
// 2-4 | 0-2 CCW
//4 ----+---- 0
//CCW-- | +- CW
// 4-6 | 6-8
// 5 6 7
// 0 1 or 2
int index = near_45 + 2*near_90;
// negating a or b reverses angle
index *= (1-2*neg_a);
index *= (1-2*neg_b);
// base is 4 if a is negative:
index += 4*(neg_a);
// base is 8 if b is negative, and a is not negative:
index += 8*(neg_b&!neg_a);
index &= 7;
return index;
これはかなりばかげていますが、ブランチはありません。また、デバッグされていません。