mpfr について
gmp をコンパイルして動かす事は出来たので、今度は mpfr をコンパイルする。
mpfr は gmp を使い、初等関数などをサポートしたライブラリで、ルート、ログ、三角関数など色々な関数を使えるようになる。
- 電卓には必須のライブラリだ
- gmp は基本的に四則演算のみを行う
mpfr をコンパイルする
まず、mpfr のソースコードを取って来る。
展開してコンパイル、ここでのキモは、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 のマスターブランチにプッシュする。~~
電卓アプリは、引き続き、機能追加などを行っていく予定。