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
この記事が気に入ったらサポートをしてみませんか?