やること
こちらのスライドに載っている「Abseilの最適化」を自前で実装してみる。
オリジナル
おそらく、スライドで「Abseilの最適化」と言っているのは、以下のソースのことだと思われる。
ここで定義されているGenerateRealFromBitsという関数は、64bitの非負整数を、指定された浮動小数点数型の[0.0, 1.0)の値に変換するものである。
自前実装
同じ関数を独自に実装する(C++20の機能を利用)。ただし、オリジナルのソースとは異なり、浮動小数点数の範囲を3種類から選択する機能や、ゼロを含むかどうかを指定する機能、指数のバイアスを指定する機能は省略している。
#include <concepts>
#include <cstdint>
#include <algorithm>
#include <bit>
#include <limits>
using namespace std;
template<floating_point RealType>
RealType GenerateRealFromBits(uint64_t n) {
return RealType(n & ~uint64_t{ 0 } << max(0, bit_width(n) - numeric_limits<RealType>::digits)) / 0x1p64f;
}
オリジナルのソースでやろうとしていることは、64bitの非負整数の先頭の0の数を指数に、最初の1から先を仮数にした浮動小数点数の生成である。これは、よくよく考えると、単に64bitの非負整数を浮動小数点に変換する際に実施している計算と同様であることが分かる。であれば、その変換を直接利用するのが手っ取り早い。
単に変換するだけだと、$[0, 2^{64})$の範囲となってしまうため、$2^{64}$で割っている。また、浮動小数点数の精度より多くのビットが存在すると、丸めで範囲外の値が生成される恐れがあるため、精度を超えるビットはマスクしている。
感想
結果的に出てきたソースを見ると、64bitの除算法に上限超過対策(ビットマスク)を入れただけのように見えるのが興味深い。