● 実行速度について
基本事項
多くの場合、fixed X の関数で構成した計算処理がボトルネックになるので、数値幅を小さくするか、fixed X の計算処理を改善/削減する方向で最適化した時に、大きな効果があります。
例1. 256bit の unsigned FIXEDVAL値を 10進数文字列に変換
#include <string.h>
#include "fixedX.h"
#define BIT 256
#define SIZE (BIT / 8)
void u256toa(PFIXEDVAL pval,char *pdest)
{
unsigned long rem;
char *ptr = pdest;
do{
fixed_div32(pval,10UL,&rem,SIZE);
*ptr++ = (char )(rem + '0');
}while(fixed_nzero(pval,SIZE));
*ptr = 0;
strrev(pdest);
}
文字列への変換処理は fixed X にも備わっていますので、例1 のような処理を使用する事は少ないかもしれません。しかし、BCD形式への変換等、このコードが基本形となる処理もありますので、記憶に留めておくと後々役に立つと思います。
例1 が大きな数値で扱われる場合についての最適化を行ってみます。
関数内にあるループが、変換する文字数分繰り返される事に注目します。ループの回数を減少させる事ができれば、fixed_div32 と fixed_nzero を実行する回数も減ります。もちろん、単純に回数を減らしただけでは、正しい実行結果が得られません。(プログラム全体として)改善前と改善後の実行結果は同じである必要があります。
例2.
#include <string.h>
#include "fixedX.h"
#define BIT 256
#define SIZE (BIT / 8)
void u256toa(PFIXEDVAL pval,char *pdest)
{
unsigned long rem,v;
char *ptr = pdest;
int i;
while(1){
fixed_div32(pval,1000000000UL,&rem,SIZE);
v = rem; i = 9;
do{
*ptr++ = (char )(v % 10 + '0');
i--;
}while((v /= 10) != 0);
if (!fixed_nzero(pval,SIZE)) break;
while(i--) *ptr++ = '0';
}
*ptr = 0;
strrev(pdest);
}
例1 は 10 の剰余を使用する方法でしたが、例2 では 1,000,000,000 の剰余を文字列に変換します。例1 よりも優雅さに欠けるかもしれませんが、効率は良くなっています(ソースコードを美しく書く事≠最適化)。最大値を与えた場合、例1 では関数fixed_div32 を 78 回呼び出すのに対し、例2 の場合は 9 回しか呼び出しません。