符号なし 128 ビット整数をリトルエンディアン順で表す 4 つの符号なし 32 ビット整数があります。
typedef struct {
unsigned int part[4];
} bigint_t;
この数値を 10 進文字列表現に変換し、ファイルに出力したいと思います。
現在、bigint_divmod10
関数を使用して数値を 10 で除算し、剰余を追跡しています。この関数を繰り返し呼び出して、数値がゼロになるまで余りを数字として出力します。かなり遅いです。これが最速の方法ですか?もしそうなら、私が見ていないこの機能を実装する賢い方法はありますか? GMP を調べてみましget_str.c
たが、かなり難解です。
編集: divmod10 関数について思いついた最速のコードは次のとおりです。
static unsigned uint128_divmod10(uint128 *value)
{
unsigned int a = value->word[3];
unsigned int b = value->word[2];
unsigned int c = value->word[1];
unsigned int d = value->word[0];
unsigned int diva = a / 5;
unsigned int divb = b / 5;
unsigned int divc = c / 5;
unsigned int divd = d / 5;
value->word[3] = diva;
value->word[2] = divb;
value->word[1] = divc;
value->word[0] = divd;
unsigned int moda = a - diva*5;
unsigned int modb = b - divb*5;
unsigned int modc = c - divc*5;
unsigned int modd = d - divd*5;
unsigned int mod = 0;
mod += moda;
unsigned int carryb = mod*858993459;
mod += modb;
if (mod >= 5) {
mod -= 5;
carryb++;
}
unsigned int carryc = mod*858993459;
mod += modc;
if (mod >= 5) {
mod -= 5;
carryc++;
}
unsigned int carryd = mod*858993459;
mod += modd;
if (mod >= 5) {
mod -= 5;
carryd++;
}
uint128_add(value, carryd, 0);
uint128_add(value, carryc, 1);
uint128_add(value, carryb, 2);
if (value->word[0] & 1) {
mod += 5;
}
uint128_shift(value, -1);
return mod;
}
add 関数は次のように定義されます。
static void uint128_add(uint128 *value, unsigned int k, unsigned int pos)
{
unsigned int a = value->word[pos];
value->word[pos] += k;
if (value->word[pos] < a) {
// overflow
for (int i=pos+1; i<4; i++) {
value->word[i]++;
if (value->word[i]) {
break;
}
}
}
}