● 実行速度について

基本事項

多くの場合、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_div32fixed_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 回しか呼び出しません。