10 の整数乗

10 の整数乗を求める関数で、[-32, 31] 内の int n に対して高速なものを作りました。

if ((np32 & ~63) == 0) のところですが、普通は if (0 <= np32 && np32 <= 63) と書くところです。後者だと cmp (整数比較)と条件ジャンプの組2つにコンパイルされるのに対し、前者は test (ビットand)と条件ジャンプの組1つで済みます。ちょっとでも速くしたかったので、前者を使用しています。テーブルの範囲もビット演算1回で済むように決めました。

コンパイラが最適化してくれてもいいと思うのですが、Visual Studio 2019 の C++ ではやってくれませんでした。もしかしたらコンパイルオプションで指定できるのかもしれません。

// <pow10n.h>

#ifndef pow10n_h
#define pow10n_h

#include <cmath>

//------------------------------------------------------------
//
// pow10n - 10 の整数乗
//

/// [-32, 31] 内の int n に対する pow(10, n) のテーブル
extern const double pow10n_table[31-(-32)+1];

/// [-32, 31] 内の int n に対して高速な 10 の整数乗
inline double pow10n(int n)
{
    extern const double pow10n_table[31-(-32)+1];
    int np32 = n + 32;
    if ((np32 & ~63) == 0) // (0 <= np32 && np32 <= 63)
        return pow10n_table[np32];
    return std::pow(10, n);
}

//------------------------------------------------------------

#endif // pow10n_h

// end of <pow10n.h>
// <pow10n.cpp>

#include "pow10n.h"

//------------------------------------------------------------
//
// pow10n - 10 の整数乗
//

// [-32, 31] 内の int n に対する pow(10, n) のテーブル
const double pow10n_table[31-(-32)+1] = {
    1e-32,
    1e-31,
    1e-30,
    1e-29,
    1e-28,
    1e-27,
    1e-26,
    1e-25,
    1e-24,
    1e-23,
    1e-22,
    1e-21,
    1e-20,
    1e-19,
    1e-18,
    1e-17,
    1e-16,
    1e-15,
    1e-14,
    1e-13,
    1e-12,
    1e-11,
    1e-10,
    1e-9,
    1e-8,
    1e-7,
    1e-6,
    1e-5,
    1e-4,
    1e-3,
    1e-2,
    1e-1,
    1e+0,
    1e+1,
    1e+2,
    1e+3,
    1e+4,
    1e+5,
    1e+6,
    1e+7,
    1e+8,
    1e+9,
    1e+10,
    1e+11,
    1e+12,
    1e+13,
    1e+14,
    1e+15,
    1e+16,
    1e+17,
    1e+18,
    1e+19,
    1e+20,
    1e+21,
    1e+22,
    1e+23,
    1e+24,
    1e+25,
    1e+26,
    1e+27,
    1e+28,
    1e+29,
    1e+30,
    1e+31,
};

//------------------------------------------------------------

// end of <pow10n.cpp>