RXマイコン用多倍長ライブラリ (mpfr) のコンパイル

mpfr について

gmp をコンパイルして動かす事は出来たので、今度は mpfr をコンパイルする。

mpfr は gmp を使い、初等関数などをサポートしたライブラリで、ルート、ログ、三角関数など色々な関数を使えるようになる。

  • 電卓には必須のライブラリだ
  • gmp は基本的に四則演算のみを行う

mpfr をコンパイルする

まず、mpfr のソースコードを取って来る。

GNU MPFR Library

展開してコンパイル、ここでのキモは、gmp ライブラリが置いてある場所を指定する事。
※指定しないと、gmp がシェアードライブラリじゃないとリンク出来ないと思う。(前回、gmp はスタテックライブラリを作成した)

% ./configure --host=rx-elf --prefix=/usr/local/rxlib --with-gmp=/usr/local/rxlib
% make
% make install

mpfr を使ってみる

    void test_mpfr_()
    {
        mpfr_t a, c;

        mpfr_init2 (c, 50);
        mpfr_set_d (c, 2.0, MPFR_RNDD);
        mpfr_init2 (a, 50);

        mpfr_sqrt(a, c, MPFR_RNDD);

        mpfr_printf("sqrt(2): %.50RNf\n", a);

        mpfr_clear (c);
        mpfr_clear (a);
    }
Start SCI (UART) sample for 'RX64M' 120[MHz]
SCI Baud rate (set):  115200
SCI Baud rate (real): 115355 (0.13 [%])
CMT rate (set):  100 [Hz]
CMT rate (real): 100 [Hz] (0.00 [%])
    7612058254738945
*
    9263591128439081
--------------------
70514995317761165008628990709545
sqrt(2): 1.41421356237309403525159723358228802680969238281250

なるほど、簡単だー

mpfr C++ ラッパーを試す

mpfr を使う C++ ラッパーは色々ある、boost もその一つだが、RX マイコン用にカスタマイズしないと、コンパイルが通らない。

他のラッパーも試してはみたものの、基本、どれも iostream に依存していて、組み込みマイコンとは相性が悪い・・・
※非常に巨大になる・・・

つまり、これは、またしても車輪の再発名か・・・

まぁ、でも、機能を絞るのでそんなに大変じゃないのかなと思って、実験的に作ってみた。

とりあえず、四則演算が出来れば、俺俺 Arith クラス(数式解析クラス)に組み込める。

  • 数式解析は、数学的な数式を入力して、それを計算する。
  • 掛け算、割り算が優先されるとか、括弧が優先されるとか、意外と面倒だ。
  • シンボル(変数)の展開
  • 関数の展開
  • べき乗の展開
    basic_arith クラス

とりあえず、最低限必要な部分を作ってみた

オブジェクトに対してのオペレーターをそれなりに作れば、正しく動くと思う。

mpfr.hpp を実装、最低限必要そうな部分のみ実装してある。

実装では、mpfr 名前空間を作り、「value」クラスを定義した。

value クラス内に、mpfr_t 構造体を置いて、それに対する操作を列挙した。

重要なのは、四則演算などのオペレータをオーバーロードする事だ。

        bool operator == (int v) const noexcept
        {
            return mpfr_cmp_si(t_, v) == 0;
        }
        bool operator == (long v) const noexcept
        {
            return mpfr_cmp_si(t_, v) == 0;
        }
        bool operator == (double v) const noexcept
        {
            return mpfr_cmp_d(t_, v) == 0;
        }

        value& operator = (const value& th) noexcept {
            mpfr_set(t_, th.t_, rnd_);
            return *this;
        }
        value& operator = (long v) noexcept {
            mpfr_set_si(t_, v, rnd_);
            return *this;
        }
        value& operator = (double v) noexcept {
            mpfr_set_d(t_, v, rnd_);
            return *this;
        }

        const value operator - () noexcept
        {
            value tmp(*this);
            mpfr_neg(tmp.t_, tmp.t_, rnd_);
            return tmp;
        }

        value& operator += (const value& th) noexcept
        {
            mpfr_add(t_, t_, th.t_, rnd_);
            return *this;
        }

        value& operator -= (const value& th) noexcept
        {
            mpfr_sub(t_, t_, th.t_, rnd_);
            return *this;
        }

        value& operator *= (const value& th) noexcept
        {
            mpfr_mul(t_, t_, th.t_, rnd_);
            return *this;
        }

        value& operator /= (const value& th) noexcept
        {
            mpfr_div(t_, t_, th.t_, rnd_);
            return *this;
        }

        value operator + (const value& th) const noexcept { return value(*this) += th; }
        value operator - (const value& th) const noexcept { return value(*this) -= th; }
        value operator * (const value& th) const noexcept { return value(*this) *= th; }
        value operator / (const value& th) const noexcept { return value(*this) /= th; }

このくらいで、とりあえず、basic_arith で扱えるようになった。

早速、RX72N Envision Kit で動かしてみた、問題なく計算出来るようになったー

~~ 表示関係とかが、イマイチなので、整理したら、git のマスターブランチにプッシュする。~~
電卓アプリは、引き続き、機能追加などを行っていく予定。

関数電卓サンプル