ビット演算 テクニック集

いろんなビット演算のテクニックを集めていきたいと思います。ソースは基本的にC(C++)で記述されています。
実用的なもの、面白い物何でもいいので、こんなテクニックを知ってるという方や
こんなのを思いついたという方はぜひ掲示板メールなどで教えてください。
良さそうなものはここで紹介させていただきたいと思います。ここにあるコードの改良、指摘なども大歓迎です。
また、ここにあるビット演算のテクニックはフリーです。自由に使用してもらっても結構です。
なお、ソースを送る場合はそれを納得したうえで送ってください。

目次

・整数の絶対値
・2整数のmax、min
・32ビットDIBの加算合成、パックドバイト飽和加算

 

整数の絶対値

inline int fastabs(int a)
{
 int mask = a >> 31;
 return (a ^ mask) - mask;
}

これは有名ですね。一応、紹介しておきます。
 

2整数のmax, min

inline int fastmax(int a, int b)
{
 int t = (a-b);
 return a - (t & (t >> 31));
}

inline int fastmin(int a, int b)
{
 int t = (a-b);
 return b + (t & (t >> 31));
}
 

これも有名ですが、少しアレンジしてみました。
(a&~mask)|(b&mask) のタイプはよくあるのですが、このタイプはあまり無いみたいです。
どちらが速いかはわかりませんが、とりあえず演算子の数はこっちの方が少ないです。
 

32ビットDIBの加算合成、パックドバイト飽和加算

typedef unsigned int DWORD;

inline void packed_byte_add(DWORD *a, DWORD *b)
{
 DWORD mask = (0x80808080 - ((((*a >> 1) & 0x7f7f7f7f) + ((*b >> 1) & 0x7f7f7f7f)
  + ((*a ^ *b) & 0x01010101)) >> 7 & 0x01010101)) ^ 0x80808080;
 *a = (*a & (~mask)) + (*b | mask);
}

void kasan_gousei_32bpp(DWORD *a, DWORD *b)
{
DWORD mask = (0x80808080 - (((*a & 0xfefefefe) + (*b & 0xfefefefe)
+ ((*a & *b) & 0x02020202)) >> 8 & 0x01010101)) ^ 0x80808080;
*a = (*a & (~mask)) + (*b | mask);
}

32ビット符号なし整数を、1バイト整数4個と見て、それぞれに飽和加算をします。
kasan_gouseiの方は32ビットDIBにて最上位1バイトが使用されていないのを利用し
少し最適化してあります。なので、最上位の計算結果は保障されません。
+ (*a & *b) & 0x02020202) を無くせば誤差は少々出ますが、多少高速になります。
MMX使えば一瞬です^^;
これは学校の友人と考え出したんですが、これも結構有名みたいですね。

 

戻る