mpfr_expr チュートリアル
このチュートリアルでは、GNU MPFR で計算した参照結果に対して bin_float を検査する方法を説明します。サポートされる行指向の形式は 3 つあります。MPFR 自身の平方根テストデータ、整数べき乗、初等関数マトリクスです。ファイルを文書に構文解析し、実行して、要約を読みます。コマンドラインランナーは mpfr_expr_cli です。
クイックスタート
moon.pkg にパッケージを追加します。
import {
"Luna-Flow/floating/frontend/mpfr_expr",
}
53 ビット、最近接丸めで、1 つの平方根 を検査します。
///|
test "quick start" {
let rows =
#|# input_precision output_precision rounding input expected
#|53 53 n 0x10000000000000p-1074 0x10000000000000p-563
#|
let document = @mpfr_expr.parse_sqrt_data("sqrt.txt", rows).unwrap()
let summary = @mpfr_expr.execute_sqrt_data(document)
inspect(summary.passed_cases(), content="1")
inspect(summary.success(), content="true")
}
数値は 16 進の仮数と 2 進の指数で書きます。0x10000000000000p-1074 は です。
日常的なタスク
フラグ付きの初等関数
初等関数の行は、関数名、出力の精度と丸め、オペランド、期待される結果、3 つの例外フラグ(inexact、invalid、ゼロ除算)を記述します。使わないオペランドは -(第 2 オペランド)と 0(整数オペランド)で書きます。
///|
test "elementary rows" {
let rows =
#|# mpfr-elementary-v1
#|# op prec rnd x y n expected inexact invalid divbyzero
#|exp 24 n 0x0p0 - 0 0x1p0 0 0 0
#|ln 53 n 0x0p0 - 0 -inf 0 0 1
#|sqrt 53 z -0x1p0 - 0 nan 0 1 0
#|rootn 53 n 0x1bp0 - 3 0x3p0 0 0 0
#|hypot 53 d 0x3p0 0x4p0 0 0x5p0 0 0 0
#|
let document = @mpfr_expr.parse_elementary_data("elem.txt", rows).unwrap()
let summary = @mpfr_expr.execute_elementary_data(document)
inspect(summary.total_cases(), content="5")
inspect(summary.passed_cases(), content="5")
}
ln(0) = -inf はゼロ除算を発生させ、sqrt(-1) は NaN を返す無効演算です。どちらのフラグも検査の対象です。
整数べき
pow の行は、各数値を係数、2 進指数、符号に分けて記述します。
///|
test "integer power rows" {
// (3 * 2^-1)^3 = 27/8 at 11 bits, exact
let rows =
#|11 n 3 -1 0 3 6c0 -9 0 0
#|
let document = @mpfr_expr.parse_pow_data("pow.txt", rows).unwrap()
let summary = @mpfr_expr.execute_pow_data(document)
inspect(summary.passed_cases(), content="1")
}
各フィールドは、精度、丸め、入力の係数(16 進数字)、入力の指数、入力の符号(1 は負)、整数の指数、期待される係数、期待される指数、期待される符号、inexact フラグです。ここで 0x6c0p-9 は です。
失敗を読む
///|
test "a failing row" {
let rows =
#|# mpfr-elementary-v1
#|exp 24 n 0x0p0 - 0 0x2p0 0 0 0
#|
let summary = @mpfr_expr.execute_elementary_data(
@mpfr_expr.parse_elementary_data("bad.txt", rows).unwrap(),
)
let result = summary.results()[0]
inspect(result.id(), content="exp:2")
inspect(
result.message(),
content="elementary mismatch: expected 0x1p1 flags=false/false/false, actual 0x1p0 flags=false/false/false",
)
}
ID は演算(または sqrt/pow)と行番号です。
構文解析エラー
不正な行はすべて行番号付きで報告され、文書は返されません。
///|
test "parse errors" {
match @mpfr_expr.parse_sqrt_data("bad.sqrt", "53 53 x 0x1p0 0x1p0\n53 53\n") {
Err(diagnostics) =>
inspect(
diagnostics.map(d => d.line().to_string() + ": " + d.message()).join("; "),
content="1: invalid or unsupported MPFR data_check directive; 2: MPFR data_check row must contain five fields",
)
Ok(_) => fail("expected diagnostics")
}
}
さらに進んで
- コーパス。
just conformance run binaryは、固定された MPFR のtests/data/sqrtファイルとコミット済みの初等関数マトリクスtestdata/bin_float/mpfr-4.2.2-elementary.txtを TestFloat と合わせて実行します。検証 を参照してください。初等関数データとべき乗データの生成器はtools/generate_mpfr_elementary_oracle.cとtools/generate_mpfr_pow_oracle.cです。 - どのパーサが使われるか。 CLI は、ファイルが
mpfr-elementary-v1を含めば初等関数形式、input_coefficient_hexを含めばべき乗形式、それ以外は平方根形式を選びます。マーカーはコメント行に置いてください。
よくある落とし穴
- 初等関数の行はエンコーディングではなく数値を比較します。 そこでは
+0と-0は等しいとみなされ、任意の NaN が期待値nanにマッチします。平方根とべき乗の行は、ゼロの符号を含めてBinFloat全体を比較します。 - 平方根のフラグは検査されません。
sqrtのデータ行は値だけを比較します。 - 指数範囲はありません。 行は有界でないコンテキストで実行されます。オーバーフロー、アンダーフロー、非正規化数の範囲は存在せず、オーバーフローやアンダーフローを報告する初等関数やべき乗の行は失敗します。
- 2 項演算には第 2 オペランドが必要です。 第 2 オペランドが
-である初等関数のpow、hypot、atan2の行はパーサには受理されますが、実行時に中断します。
次のステップ
- すべての項目と正確なフィールド配置については mpfr_expr API。
- 合格規則については mpfr_expr 設計。
- テスト対象の関数については bin_float チュートリアル。