ここに少し数学があります。単純に、各要素を2ビットで記述できるので、4つの要素を1バイトにパックして、適切なランダムアクセスを取得できます。4つの要素には34 = 81の状態があるため、81 /256≈32%の使用量になります。バイト境界にとどまりたい場合は、2 8に収まる最も近い3の累乗、つまり3 5 = 243を探すことができます。つまり、1バイトで5つの連続する要素のすべての可能な状態を列挙する場合、243 /256≈95%のスペース効率があります。
大量のデータを処理していて、すべてを物理メモリに収めることができず、アルゴリズムを分割して一度に小さなチャンクで実行できない場合を除いて、このパッキングをメモリで行うことは意味がありません。効率的な計算を行うには、少なくとも1バイト(uint8_t
)、またはマシンワード(uint8fast_t
)を使用してデータを格納する必要があります。データをディスクにシリアル化し、テラバイト単位のデータがRAID-50ストレージに対して高すぎることがわかった場合にのみ、複雑なパッキングスキームを検討することをお勧めします。(ただし、データをパイプでつなぐこともできgzip
ます。これにより、基本的にすべてが実行されます。)
バイトから5つの要素を取得するための基本的なデコードアルゴリズムは次のとおりです。
unsigned int get_tristate(unsigned char const n, size_t const i)
{
/* Conditions: n in [0, 243)
i in [0, 5)
Returns: the i^th trivalent element encoded in n, in [0, 2).
*/
static unsigned int const powers[] = { 1, 3, 9, 27, 81, 243 };
return (n / powers[i]) % powers[i + 1];
}