Intel の十進浮動小数点ライブラリを使ってみる (1)

以下で使用している OS は CentOS7.

ライブラリのダウンロード

ライブラリのソースは,以下からダウンロードできる.

ライブラリのビルド

ダウンロードしたファイル IntelRDFPMathLib20U2.tar.gz を展開する.

LIBRARY サブディレクトリで,

$ make CC=gcc CALL_BY_REF=0 GLOBAL_RND=0 GLOBAL_FLAGS=0 UNCHANGED_BINARY_FLAGS=0

これで,ライブラリファイル libbid.a が生成される.

ライブラリの利用

ビルドしたライブラリ libbid.a を適当なディレクトリにコピーする.

TEST サブディレクトリの test_bid_conf.h と test_bid_functins.h を,適当なディレクトリの bid_conf.h,bid_functions.h にコピーする.

(以下,ライブラリもヘッダファイルもソースと同じディレクトリにあるものとする)

サンプルプログラム

関数 bid128_from_string() というものがあったりするので,文字列を 128bit 十進浮動小数点数として読み込ませるものを作成してみた.

/*
* str2bid128.c
*/

#include <stdio.h>
#include <stdlib.h>
#include "bid_conf.h"
#include "bid_functions.h"

#define PRINT_DECIMAL_EXCEPTIONS(func, fpsf) {				\
   fprintf(stderr, "FLOATING-POINT EXCEPTIONS in %s: fpsf=0x%x\n", func, fpsf); \
   if (fpsf & DEC_FE_INVALID)   fprintf(stderr, "  INVALID OPERATION\n"); \
   if (fpsf & DEC_FE_UNNORMAL)  fprintf(stderr, "  UNNORMAL\n");	\
   if (fpsf & DEC_FE_DIVBYZERO) fprintf(stderr, "  DIVISION BY ZERO\n"); \
   if (fpsf & DEC_FE_OVERFLOW)  fprintf(stderr, "  OVERFLOW\n");	\
   if (fpsf & DEC_FE_UNDERFLOW) fprintf(stderr, "  UNDERFLOW\n");	\
   if (fpsf & DEC_FE_INEXACT)   fprintf(stderr, "  INEXACT RESULT\n"); \
 }

int main(int argc, char **argv)
{
 if (argc < 2) {
   fprintf(stderr, "\
Usage: %s <string_to_convert>\n\
Tries to convert the string to BID_UINT128 (Decimal128) and ejects the exceptions if any.\n\
", argv[0]);
   exit(1);
 }

 unsigned int fpsf=0;

 BID_UINT128 d = bid128_from_string(argv[1], BID_ROUNDING_TO_NEAREST, &fpsf);
 PRINT_DECIMAL_EXCEPTIONS("bid128_from_string", fpsf);

 if (bid128_isNaN(d)) printf("\"%s\" is NaN\n", argv[1]);
 else printf("\"%s\" is a valid number\n", argv[1]);

 char str[256];
 fpsf = 0;
 bid128_to_string(str, d, &fpsf);
 printf("d=%s\n", str);
 PRINT_DECIMAL_EXCEPTIONS("bid128_to_string", fpsf);

 return 0;
}
/* bottom of file */

せっかくなので,bid128_to_string() や,数値かどうかを判定する bid128_isNaN() も使用してみた.

コンパイル

$ gcc -o str2bid128 str2bid128.c libbid.a

実行してみる

Usage

$ ./str2bid128
Usage: ./str2bid128 <string_to_convert>
Tries to convert the string to BID_UINT128 (Decimal128) and ejects the exceptions if any.

"3.14" を読み込ませてみる

$ ./str2bid128 3.14
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x0
"3.14" is a valid number
d=+314E-2
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0

仮数部桁溢れで INEXACT 例外が発生している様子 (34桁なら問題なし.35桁で例外発生)

$ ./str2bid128 1234567890123456789012345678901234
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x0
"1234567890123456789012345678901234" is a valid number
d=+1234567890123456789012345678901234E+0
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0
$ ./str2bid128 12345678901234567890123456789012345
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x20
 INEXACT RESULT
"12345678901234567890123456789012345" is a valid number
d=+1234567890123456789012345678901234E+1
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0

指数部桁溢れで OVERFLOW 例外が発生している様子 (1*10^6144なら問題なし.1*10^6145で溢れ)

$ ./str2bid128 1e6144
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x0
"1e6144" is a valid number
d=+1000000000000000000000000000000000E+6111
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0
$ ./str2bid128 1e6145
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x28
 OVERFLOW
 INEXACT RESULT
"1e6145" is a valid number
d=+Inf
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0

指数部桁溢れで UNDERFLOW 例外が発生している様子

$ ./str2bid128 1e-6176
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x0
"1e-6176" is a valid number
d=+1E-6176
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0
$ ./str2bid128 1e-6178
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x30
 UNDERFLOW
 INEXACT RESULT
"1e-6178" is a valid number
d=+0E-6176
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0

非数値文字列 "ABC" を読み込ませた様子

$ ./str2bid128 ABC
FLOATING-POINT EXCEPTIONS in bid128_from_string: fpsf=0x0
"ABC" is NaN
d=+NaN
FLOATING-POINT EXCEPTIONS in bid128_to_string: fpsf=0x0

この記事が気に入ったらサポートをしてみませんか?