User-defined literals で固定長の Boost.Multiprecision を生成

template で受け取る User-defined literals を定義すれば sizeof...(cs) で数値の長さ(桁数)が取得出来ます。

template<char ...cs>
constexpr std::size_t
operator "" _cpp_int(){
    return sizeof...(cs);
}

static_assert(1234_cpp_int == 4, "");
static_assert(123456789_cpp_int == 9, "");


で、その数値の桁数からビット幅を計算して固定長の Boost.Multiprecision を生成出来ないかなーと思ってやってみたんですがビット幅を取得する計算方法がよく分からなかったのでとりあえず適当にやってみた/(^o^)\
やや多めのビット幅で定義するけど一応は動作するはず。

[ソース]

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>


template<int Precision>
using cpp_int = boost::multiprecision::number<
    boost::multiprecision::cpp_int_backend<
        Precision,
        Precision,
        boost::multiprecision::signed_magnitude,
        boost::multiprecision::unchecked,
        void
    >
>;


template<char ...cs>
cpp_int<std::size_t(sizeof...(cs) * 3.34)>
operator "" _cpp_int(){
    char const str[] = { cs..., '\0' };
    return cpp_int<std::size_t(sizeof...(cs) * 3.34)>(str);
}


int
main(){
    auto n = 573147844013817084101_cpp_int;
    std::cout << n << std::endl;
    std::cout << std::numeric_limits<decltype(n)>::digits << std::endl;

    auto m = 927372692193078999176_cpp_int;
    std::cout << m << std::endl;
    std::cout << std::numeric_limits<decltype(m)>::digits << std::endl;

    auto cpp128 = 340282366920938463463374607431768211455_cpp_int;
    std::cout << cpp128 << std::endl;
    std::cout << std::numeric_limits<decltype(cpp128)>::digits << std::endl;

    auto cpp256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935_cpp_int;
    std::cout << cpp256 << std::endl;
    std::cout << std::numeric_limits<decltype(cpp256)>::digits << std::endl;
    
    return 0;
}

[出力]

573147844013817084101
70
927372692193078999176
70
340282366920938463463374607431768211455
130
115792089237316195423570985008687907853269984665640564039457584007913129639935
260


で、ここまでやって思ったけど別にビット幅を切り詰めなくても int128_t や int256_t を使用するようにしたほうがいい気がした。


ちなみに gcc 4.8 が古いと上記のコードはコンパイルに失敗する可能性があります。
わたしの環境だと去年ビルドしたものでコンパイルエラーになりました。
最新のものだと多分大丈夫。

[boost]

  • ver 1.53.0

[コンパイラ]

  • g++ (GCC) 4.8.0 20130210 (experimental)