多倍長浮動小数点数
前回、電卓アプリを実験的に作ってみた。
ただ、「240MHz で動く32ビットマイコンなのに精度が64ビットの浮動小数点」なの?
これは、かなり痛い・・・
そこで、多倍長浮動小数点数などを扱えるライブラリを利用する事にした、最初、boost にある「Boost Multiprecision Library」を利用してみた。
何の問題もなく、簡単に数十桁の演算が出来る事を確認した。
しかし、RX マイコンの環境(Renesas GNU RX gcc compiler 8.3.0)では、これらのライブラリを含んだコードをコンパイル出来ない。
これは、mingw64 用の boost ソースコードを使っている為で、本来なら、boost のソースコードを RX マイコン用にカスタマイズしなければならない。
- 多くのライブラリは、専用の物を作らなくても、対応可能な事から、この問題を避けてきた。
- コンパイルで失敗する主な理由は、スレッド関係のようだ・・
しかし、boost を RX マイコン用にカスタマイズするのは、それはそれで大変そうだと思い、少し発想を変えてみようと思った。
また、boost のライブラリは、速度的には、古くからある、gmp、mpfr ライブラリより劣ると言われている。
※しかしながら、gmp や mpfr はライセンスが GNU なので、あえて boost を使う理由があると思える。
- boost には、これら(gmp mpfr)のライブラリをラップしたクラスもあるが、これは完全に環境依存となっている。
- Multiprecision のコード関係を RX マイコンに対応させるのはそれなりの労力だと思える。
とりあえず、gmp ライブラリをコンパイルしてみる。
操作は、MSYS2 上のコンソールで行う。
ソースコードを取ってくる。
見慣れない「lz」拡張子に対応する為、lzip をインストールしておく。
% pacman -S lzip
続いて解凍する。
tar --lzip -xvf gmp-6.2.1.tar.lz
.configure するには、少し問題がある、gmp の configure は、Renesas GNU rx-elf 関係があるパスを正しく認識しない。
これは、パスにスペースが含まれる為で、configure を直すのも大変そうなので、とりあえず、rx-elf 関係を、mingw の「/usr/local」以下にコピーして対応した。
% cd /usr/local
% cp -r /c/Users/hira/AppData/Roaming/GCC\ for\ Renesas\ RX\ 8.3.0.202004-GNURX-ELF/rx-elf .
rx-elf 関係のパスを変更して、bash を再起動 (.bash_profile)
# rx-elf path
# PATH=$PATH:/usr/local/rx-elf/bin
# PATH=$PATH:/C/'Program Files (x86)'/'GCC for Renesas RX 8.3.0.202002-GNURX-ELF'/rx-elf/rx-elf/bin
# PATH=$PATH:/C/Users/hira/AppData/Roaming/'GCC for Renesas RX 8.3.0.202004-GNURX-ELF'/rx-elf/rx-elf/bin
PATH=$PATH:/usr/local/rx-elf/rx-elf/bin
configure を実行:
% rx-elf-gcc --version
rx-elf-gcc.exe (GCC_Build_20201001) 8.3.0.202004-GNURX 20190222
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% cd /d/Git/RX/gmp/gmp-6.2.1
% ./configure --host=rx-elf --prefix=/usr/local/rxlib --disable-shared
...
Version: GNU MP 6.2.1
Host type: rx-unknown-elf
ABI: standard
Install prefix: /usr/local/rxlib
Compiler: rx-elf-gcc
Static libraries: yes
Shared libraries: no
% make
% make install
本来、RX コア別の最適化オプションを指定した方が良いが、v1, v2, v3 で利用出来るように、「素」の状態でコンパイルした。
実際に使ってみる
とりあえず、RX64M で実験した。
/usr/local/rxlib 以下に gmp 関係のライブラリがあるので、その設定を追加する。
実験コードを(WEB からコピペ)
void test_gmp_()
{
mpz_t x, y, result;
mpz_init_set_str(x, "7612058254738945", 10);
mpz_init_set_str(y, "9263591128439081", 10);
mpz_init(result);
mpz_mul(result, x, y);
gmp_printf(" %Zd\n"
"*\n"
" %Zd\n"
"--------------------\n"
"%Zd\n", x, y, result);
/* free used memory */
mpz_clear(x);
mpz_clear(y);
mpz_clear(result);
}
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
#
とりあえず問題無さそうだ。
RX マイコンに最適化するには、アセンブラのコードを gmp に追加する必要がありそうだが、今後の課題とする。
今回はここまで。