プログラミング
Beeg floatライブラリ、Fabrice Bellard氏のlibbfのRustポート
Beeg float library, a Rust port of Fabrice Bellard's libbf (github.com)
要約
libbeefは、Fabrice Bellard氏が開発した高精度浮動小数点ライブラリlibbfをRustで再実装したものです。IEEE 754のセマンティクスを完全にサポートし、超越関数や10進数浮動小数点も扱えます。Rustのみで依存関係がなく、no_std環境にも対応しており、バイナリサイズも小さいのが特徴です。
全文翻訳
libbeef
Fabrice Bellard氏のlibbfの高精度浮動小数点ライブラリのRustによる移植。
名前は「Beeg Float」の略です。
完全なIEEE 754セマンティクス:符号付きゼロ、NaN、無限大、設定可能な指数幅、サブノーマル、5つの丸めモードすべて、5つのステータスフラグすべて。
超越関数:exp、log、pow、sin、cos、tan、atan、atan2、asin、acos。
独立した基数10演算を備えた10進浮動小数点(BigDecimal)。
no_std互換(allocが必要)。
依存関係ゼロのピュアRust。
簡単な使用例
use libbeef::format::formats;
use libbeef::Float;
type Quad = Float<formats::Binary128>;
fn main() {
let a: Quad = "3.14159265358979323846".parse().unwrap();
let b: Quad = "2.71828182845904523536".parse().unwrap();
let result = (a * b).sin();
println!("{result}"); // 0.773942685266708278263054855332479932...
}
Float<F>は値をコンパイル時のフォーマットとペアにするため、*や.sin()は128ビット精度と丸めto-nearest-evenを自動的に使用します。各呼び出しサイトでフォーマット引数は不要です。
パフォーマンス
libbeefは、C言語のlibbfと同じアルゴリズムを実装しています:NTTベースの乗算、除算/平方根のためのニュートン反復、超越関数のためのAGM/バイナリ分割。
各演算クラスに対して最適な漸近計算量を持っています:
演算クラス | 計算量 | アルゴリズム
---|---|---
加算、減算、比較 | O(n) | 線形スキャン
乗算 | O(n log n) | 数論変換 (NTT)
除算、平方根 | O(M(n)) | NTT上のニュートン反復
exp、log、sin、… | O(M(n) · log n) | AGM / バイナリ分割
経験的に(詳細はdocs/benchmark-report.mdを参照)、libbeefはRustの境界チェックとアロケーションモデルによる定数ファクターのオーバーヘッドを伴いながら、C言語のlibbfのスループットを追跡しています。
op | 256ビット | 30,000ビット | 300,000ビット | vs libbf | vs rug (GMP/MPFR)
---|---|---|---|---|---
mul | 6.7 ns/limb | 84 ns/limb | 100 ns/limb | 1.3–2.0× | 0.9–1.3×
div | 17.3 ns/limb | 515 ns/limb | 659 ns/limb | 1.1–1.4× | 2.6–3.5×
sqrt | 38.3 ns/limb | 384 ns/limb | 597 ns/limb | 1.2–1.3× | 3.2–4.3×
sin | 1051 ns/limb | — | — | 0.7× (高速) | 3.6×
乗算の行が最も情報量が多いです:二次アルゴリズムであれば、オペランドサイズの10倍の増加ごとに約10倍の増加(47 → 469 → 4688リム)を示すはずですが、libbeefは4.2倍、次に1.2倍と増加しており、これはC言語のオリジナルと同じ形状のO(n log n) NTTエンベロープです。
300,000ビットでは、libbeefはlibbfの約2倍、GMPの1.3倍でありながら、num-bigintの学校法/Toom乗算よりも4倍高速です。
超越関数については、libbeefはsin/cos/tan/powでC言語のlibbfに匹敵するかそれを上回り、log/atanでは15%以内です。MPFRへの一貫した3~5倍のギャップはアルゴリズムによるものです(MPFRはこれらの関数に異なる、より優れたアルゴリズムを使用しており、C言語のlibbfも同じギャップを示しています)。除算と平方根は、GMP/MPFRに対してより大きな定数ファクターのギャップ(約3倍)を示します。これはlibbfのニュートン法による逆数計算アプローチとGMPの最適化された分割統治法との固有の特性であり、C言語のオリジナルでも同じ比率が見られます。
libbeefを使う理由
1. ピュアRust、システム依存なし。
rug/GMPはCコンパイラ、システムGMP/MPFRライブラリ、ホストをプローブするビルドスクリプトを必要とします。libbeefはビルドスクリプトなしでcargo addするだけで済み、-lmやpkg-configも不要です。アロケーション以上のファイルI/O、スレッド、システムコールは必要ありません。
2. 小さなバイナリフットプリント。
GMP/MPFRを静的にリンクした場合、2つの数値を乗算してsinを計算するだけの簡単なプログラムのサイズは以下のようになります:
ライブラリ | バイナリサイズ(ストリップ後)
---|---
libbeef | 482 KiB
num-bigint (整数のみ、三角関数なし) | 448 KiB
malachite (整数のみ、三角関数なし) | 658 KiB
rug (GMP + MPFR 静的リンク) | 680 KiB
libbeefは、malachiteやrugが整数のみで必要とするよりも少ないスペースで、完全な浮動小数点演算と超越関数を提供します。num-bigintのバイナリが小さいのは、sinを全く計算できないため、浮動小数点レイヤーがないからです。
3. 正確で完全。
libbeefは、libbf自身の検証スイートをすべての演算、精度、丸めモードでパスします。これは「十分良い」近似ライブラリではなく、設定可能な指数幅とサブノーマルを備えたIEEE 754に準拠した正しく丸められた演算を実装しています。
4. no_std対応。
allocのみが必要です。ファイルI/O、スレッド、アロケーション以外のシステムコールはありません。
5. より寛容なライセンス。
libbeefはMITライセンスであり、GMP/MPFRはLGPLです。これにより、LGPLに対する追加の法的レビューが望ましくないライセンスに敏感なプロジェクトにとって、libbeefはより良い選択肢となります。
他のものを使用すべき場合
高精度(10,000ビット超)での最大スループット:
GMP/MPFR(rug経由)は、乗算で約2~3倍、除算で約3倍優れた定数を持つ、高度に最適化されたFFTおよびToom-Cookスタックを備えています。百万ビット精度のns/opがボトルネックになる場合は、rugを使用してください。
整数のみのワークロード:
浮動小数点、丸め、超越関数が不要な場合は、num-bigintまたはmalachiteが整数のみに特化したシンプルなAPIを提供します。
大規模な10進数演算:
libbeefの10進数パスは機能しますが、まだパフォーマンスチューニングされていません(ネイティブの基数10^9カーネルではなく、バイナリ変換を経由します)。
ビルドとテスト
cargo build # ビルド(デフォルト機能:std)
cargo test # 全テスト実行
cargo test --test bftest # libbf検証スイート(高速、単一シード)
cargo doc --open # APIドキュメント生成と表示
機能
機能 | 説明
---|---
std (デフォルト) | stdサポートを有効にする
num-traits | numエコシステム向けのTrait実装
num-integer | 追加のnum整数Trait
serde | シリアライゼーションサポート
ライセンス
MIT(libbfと同じ)。