Boost.Multiprecision を調べてみた
<2012年4月6日に調査>
Boost.Multiprecision が、なんとなく良さげなライブラリに見えてきたので、落として調べてみました。
ただの調査メモなので、使い方的な入門は書いてないです。
gcc で使いたい
どうもテスト環境は Windows Vista 32bit, MSVC-10.0 らしいので、gcc とかで使うための設定は若干爪が甘い感じがある。
gcc の場合は __int128 を必要とするが、多分 gcc4.6 からなので、gcc4.5 以前だとコードそのままでは使えない。多分いじれば使えるのかもしれない。(ちなみに僕のところでは 4.4 , 4.5 では動かなかった)
もちろん Boost.MPL などとべったりなのでほかの Boost ライブラリもパス通す
ヘッダオンリ
Boost.Multiprecision 自体はヘッダオンリだが、下に記載したほかの多倍長整数ライブラリなどを使おうとするとそれらのライブラリのリンクが必要になる。
ほかの多倍長整数ライブラリのサポート
デフォルトでは、Boost.Multiprecision による多倍長実装がある。cpp_int と cpp_dec_float がそれなので普通はそれを使いたい。
しかし、ほかの多倍長整数系ライブラリで、以下のようなライブラリが利用できる。
Expression Templates のサポート
Boost.Multiprecision では、Expression Templates をサポートし、その有効無効も設定できる。
mp_number について
mp_number がクラスの基底らしい。テンプレートパラメータが Backend と呼ばれるポリシークラスで、ポリシーベースなクラス設計がされているらしい。これに GMP 用のポリシー等を設定した typedef が用意されている。
// boost/multiprecision/mp_number.hpp namespace boost { namespace multiprecision { /* Backend - ポリシークラス ExpressionTemplates - ET を使うか否か */ template<class Backend, bool ExpressionTemplates = true> { ... }; } };
数値の出力
Constructing and Interconverting Between Number Types
iostream で数値を出力可能、その際は std::numeric_limits が特殊化されているのでこれで出力桁数などを調整できる。
// 最大50桁の実数 cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; // すべての桁を出力する std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10) << df << std::endl cpp_int i = 1; i <<= 256; // 16進数で整数を出力 std::cout << std::hex << std::showbase << i << std::endl;
変換
Boost.Multiprecision 内で、int to float, int to rational, rational to float ならば変換可能。
それ以外はコンパイルエラーになるようだ。
// 多倍長整数 cpp_int cppi(2); // GMP を使った多倍長整数 mpz_int z = cppi; // 以下の変換は利用可能 cpp_rational cppr = cppi; cpp_dec_float_50 df = cppi; df = cppr; // これはコンパイルエラー cppi = df;
可変長と固定長
mp_number にはアロケータを指定できる。アロケータはデフォルトで std::allocator が使用されるが、アロケータ指定を void にすることで、固定長の多倍長整数(実数)として利用できる。固定長は 128, 256, 512, 1024 ビットなら typedef で用意されている。
#include <boost/multiprecision/cpp_int.hpp> namespace mp = boost::multiprecision; // 2048 ビット、符号なし固定長整数(ET無効) mp::mp_number<mp::cpp_int_backend<2048, false, void>, false> mp_uint_2048; // ビット数は可変の多倍長整数(ET無効) mp::mp_number<mp::cpp_int_backend<0, false>, false> mp_int_arbitrary;
できれば調べたいこと
- cpp_int, cpp_dec_float で、 ET を有効にしたときとしなかった時のパフォーマンス差