最近、整数演算だけで色々する話があったので、過去に作成したものを見直してみた。
・平方根
これは、ファミコン時代から使っていた方法をC++(C)で表現したもので。
※アルゴリズムは、コンピューターが出現する以前から知られていた数学的手法を元に
しているようで、初期のデジタルコンピューターが出現する、数十年前に既に知られて
いた方法のようである。
過去には、色々なマイコン用(6502、6809、68000、Z80)アセンブラ
で書いた記憶がある。
Cなどの高級言語では、キャーリーの扱いが無い為、シフトや、ビット操作を行う場合
無駄が多い。
アセンブラで書けば、より一層の高速化ができるけど、互換性を考えて、Cで実装して
ある。
ハードウェアーにも実装しやすく、割り算よりリソースを使わないと思われる。
※整数計算なので、「余り」がある。
ゲームにおいて平方根は、必ず必要な「道具」で、シューティングゲームの誘導ミサイ
ル、正規化、ほぼありとあらゆる場面で使うと思われる。
template <typename T> struct sqrt_t { typedef T value_type; T val; ///< 答え T mod; ///< 余り sqrt_t(T v = 0, T m = 0) : val(v), mod(m) { } }; static sqrt_t<uint16_t> sqrt16(uint16_t in) { uint32_t a = in; uint32_t b = 0x4000; for(int i = 0; i < 8; ++i) { if(a >= b) { a -= b; b = ((b + b) & 0xfffe0000) + 0x10000 + (b & 0xffff); } else { b = ((b + b) & 0xfffe0000) + (b & 0xffff); } a <<= 2; } sqrt_t<uint16_t> ans(b >> 16, a >> 16); return ans; }
・32ビット版
static sqrt_t<uint32_t> sqrt32(uint32_t al) { uint32_t ah, bh, bl; ah = bh = 0; bl = 0x40000000; for(int i = 0; i < 16; ++i) { if(al >= bl) { if(ah >= bh) { ah -= bh; al -= bl; bh += bh + 1; } else { bh += bh; } } else { if(ah >= (bh + 1)) { ah -= bh + 1; al -= bl; bh += bh + 1; } else { bh += bh; } } ah <<= 2; ah += al >> 30; al <<= 2; } sqrt_t ans(bh, ah); return ans; }