読者です 読者をやめる 読者になる 読者になる

Boost.Multiprecision アロケータを指定する

C++

Boost.Multiprecisionの多倍長演算型は、CPU/FPUがサポートする整数型よりも大きな精度を扱うため、フリーストアからメモリを確保した領域を使用します。
そのため、Boost.Multiprecisionの多倍長演算型は、アロケータを指定できるようになっています。


たとえば、無限精度の多倍長整数であるcpp_intは、以下のように定義されます。

namespace boost {
namespace multiprecision {

// アロケータで確保される型
typedef unspecified-type limb_type;

// 符号あり/なし
enum cpp_integer_type    { signed_magnitude, unsigned_magnitude };

// オーバーフロー/範囲外演算のチェックあり/なし
enum cpp_int_check_type  { checked, unchecked };

// 多倍長整数のバックエンド
template <unsigned MinDigits = 0,
          unsigned MaxDits = 0,
          cpp_integer_type SignType = signed_magnitude,
          cpp_int_check_type Checked = unchecked,
          class Allocator = std::allocator<limb_type> > // アロケータの型
class cpp_int_backend;

// 多倍長整数型の定義
typedef number<cpp_int_backend<> > cpp_int;
}}

cpp_int_backendに指定するアロケータは、デフォルトでstd::allocatorが使用されますが、このテンプレートパラメータを変更することで、自前のアロケータを指定できます。
以下、アロケータの設定例です。適当なアロケータが見つからなかったので、デフォルトのstd::allocatorを明示的に指定しています。

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

namespace mp = boost::multiprecision;

using my_cpp_int = mp::number<mp::cpp_int_backend<
    0,                              // 最小ビット数の指定なし
    0,                              // 最大ビット数の指定なし
    mp::signed_magnitude,           // 符号あり
    mp::unchecked,                  // オーバーフローと符号のチェックをしない
    std::allocator<mp::limb_type>   // アロケータの指定
>>;

int main()
{
    my_cpp_int x = 123;
    std::cout << x << std::endl;
}


それから、cpp_int_backendはアロケータオブジェクトへの参照を返すallocator()メンバ関数を持っているので、これを使用してアロケータオブジェクトを設定・取得できます。

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

namespace mp = boost::multiprecision;

int main()
{
    mp::cpp_int x;

    std::allocator<mp::limb_type> alloc;
    x.backend().allocator() = alloc;

    x = 123;

    std::cout << x << std::endl;
}
123

ただし、この機能は1.53.0時点ではアンドキュメントなので、自己責任で使ってください。