これは、アセンブラ時代に、サインテーブルを生成する方法を色々試して、ある程度
成果のあった方法です。
※浮動小数点の sin で求めた値と微妙に違うところもありますが、実用性は十分あり
ます。
現在の C++11 以降では、constexpr でコンパイル時に計算して、定数としてソースコ
ードにテーブルを埋め込む事ができるので、必要性は薄いのですが、知っていれば、
応用範囲は広いでしょう。
ハードウェアーに実装して、周波数シンセサイザや音源の波形ベースに使う事も考え
られます。
x' = x・cos(s) - y・sin(s)
y' = x・sin(s) + y・cos(s)
s が十分小さい場合、以下のように近似できる。
cos(s) ≒ 1
sin(s) ≒ s
x' = x - y・s
y' = x'・s + y
テーブル生成に使っていますが、連続性がある場合は、リアルタイムに計算する事も
できます。(こちらの方が応用性があります)
非常に古いですが、1979年に発売された、ナムコのギャラクシアンで、編隊が、
実機の手前で、回転したり、サインカーブ的な軌跡で攻撃してくる場面がありますが、
この原理が使われていました。
※この当時、安易にテーブルにする人が多い中で、真のエンジニアでした。
また、単振動を使って、サインテーブルを計算する方法もあるかと思いますが、周期
を決定する定数を求めるのは、整数計算だけでは、簡単では無いと思えます。
テーブル生成では、テーブルのサイズは、2のN乗の方が、扱いやすいので、sの定
数を求める場合は、全円周(2・π)を、テーブル長で割る必要があります。
template <uint16_t shi, uint16_t len> class sin_cos { static const uint32_t pai_ = 0xC90FDAA2; ///< 円周率(3.141592654 * 2^30) static const uint32_t pai_shift_ = 30; ///< 円周率、小数点位置 uint16_t tbl_[(1 << shi) + 1]; void build_() { int16_t gain = 16; // 精度を確保する為の下駄 int64_t x = len << gain; // cos(0) の値 int64_t y = 0; // sin(0) の値 for(uint16_t i = 0; i < ((1 << shi) + 1); ++i) { tbl_[i] = y >> gain; // pai_ のビット位置補正 // 全周は、2・πなので+1 x -= (static_cast(pai_) * y) >> (pai_shift_ + shi + 1); y += (static_cast (pai_) * x) >> (pai_shift_ + shi + 1); } } public: sin_cos() { build_(); } };