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

多倍長浮動小数点数

前回、電卓アプリを実験的に作ってみた。

ただ、「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 上のコンソールで行う。

gmp.org

ソースコードを取ってくる。

見慣れない「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 に追加する必要がありそうだが、今後の課題とする。

今回はここまで。