ソフトな忘却力(26) GMP、The GNU MP Bignum Library

Joseph Halfmoon

単精度浮動小数点数ですら恐れ多くて使えない、しがないマイコン屋にとっては多倍長精度演算ライブラリなどはまずは無縁な存在であります。しかし稀にその名を目にすることがあります。何かの事情でソースからgccをビルドしなけりゃならないときでしょう。gmpを使えるようにしておいてね、と言われます。たまには使ってみたいもんデス。

※「ソフトな忘却力」投稿順 Index はこちら

GMP

GMPは多くのオープンソースソフトウエアが呼び出しているんじゃないかと思われるGNU様の多倍長数値演算ライブラリであります。メモリのゆるす限りダラダラ(すみません)と長い桁数の数値を計算できるもの。有効数字3桁でほぼほぼ生きてきたものにとっては過ぎたるものであります。

御本家ホームページへのリンクが以下に。

The GNU Multiple Presicion Arithmetic Library

今回も例によってWindows11上のUbuntu 20.04LTSを使用して実験してみましたが、何もしなくても libgmp 自体はインストール済でした。当然のように各種のソフトウエアが呼び出しているためかと推察します。

ただ、「開発用」の libgmp-dev は当然のように未インストールであったので、それをインストールいたしました。ドサクサまぎれにドキュメントと、libmpfr-devまでインストールしているところが以下に。

sudo apt install libgmp-dev gmp-doc libgmp10-doc libmpfr-dev libmpfr-doc

libmpfrは、GMPの友、また後で練習してみるつもりなんでございます。ドキュメントをインストールしておけば、gnuツールなので、infoコマンドにて充実のドキュメントを読むことができまする。

info gmp
練習用に作成したソースコード

あくまで「C」ということで作成いたしました練習コードが以下です。

    • mpz_t型、多倍長整数
    • mpf_t型、多倍長浮動小数

であります。他にもレシオ型(Q)などもあるみたいですが、今回はやってません。

以下の整数型では特に桁数を指定せず「成り行き」でお願いしとります。また浮動小数の方は特に桁数を指定しないと「意外とビット幅が狭い」デフォルト値で計算してくれるようだったので、後でちょっと長めに設定しなおしとります。

なおソース中に無作法にもリテラルで「10」と書いてしまっているのは10進数指定です。当然16進含む各種進数対応であります。浮動小数点数デフォルト桁数の指定はビット単位(2進)みたいです。それに対してgmp_printfの浮動小数点数の表示桁数の指定は10進指定です。

マニュアル読むと変数の初期化と値の代入を一度にやるような関数もあるのですが、以下ではX=z(整数)、X=f(浮動小数)のどちらも同じ手順でやってます。

    1. mpX_initで変数をゼロ初期化
    2. mpXi_init_set_strで文字列から初期値を作って代入
    3. そのあと計算。整数型は足し算、浮動小数型は割り算。
    4. gmp_printf使って「多倍長」の印字

ソース全文が以下に。

#include <stdio.h>
#include <gmp.h>

int main (void)
{
    mpz_t  i, j, k;
    mpf_t  a, b, c;
    mpf_t  d, e, f;
    mp_bitcnt_t dp = mpf_get_default_prec();
    mpz_init (i);
    mpz_init (j);
    mpz_init (k);
    mpz_init_set_str (i, "11112222333344445555666677778888", 10);
    mpz_init_set_str (j, "88887777666655554444333322221111", 10);
    mpz_add(k, i, j);
    gmp_printf ("i+j=%Zd\n", k);
    mpf_init (a);
    mpf_init (b);
    mpf_init (c);
    mpf_init_set_str (a, "1.0", 10);
    mpf_init_set_str (b, "3.0", 10);
    mpf_div(c, a, b);
    gmp_printf ("default prec: %d\n", dp);
    gmp_printf ("a/b=%.*Ff\n", 32, c);
    mpf_set_default_prec(128);
    mpf_init (d);
    mpf_init (e);
    mpf_init (f);
    mpf_init_set_str (d, "1.0", 10);
    mpf_init_set_str (e, "3.0", 10);
    mpf_div(f, d, e);
    gmp_printf ("d/e=%.*Ff\n", 32, f);
    return 0;
}
ビルドして実行

ビルドは簡単。ライブラリ libgmp をリンクしないといけないのでその指定のみ。

gcc tstGMP.c -lgmp

実行結果が以下に。

gmpResults

整数型の足し算、10進で32桁、計算されとります。この桁数は入力桁数の「成り行き」できまっているものと思われます。知らんけど。

浮動小数点数は、デフォルトのお任せ指定であると上記のa/bのように小数点以下21桁までで切り捨てられてるみたいです。一方、メモリを128ビット確保するようにデフォルト桁数を変更した後の d/e では32桁まで表示されとります。

多倍長というわりに短い桁数で実験だけれども動作はOKよ。

ソフトな忘却力(25) WSL2とWindows11連携でサウンドファイル生成なんのその へ戻る

ソフトな忘却力(27) MPFR, the MUltiple Precision Floating-Point Reliable Library へ進む