mpfr_expr 教程
本教程介绍如何用 GNU MPFR 计算出的参考结果检验 bin_float。支持三种面向行的格式:MPFR 自带的平方根测试数据、整数幂,以及初等函数矩阵。你将把文件解析为文档,执行它,并读取摘要。命令行运行器是 mpfr_expr_cli。
快速入门
将该包添加到 moon.pkg:
import {
"Luna-Flow/floating/frontend/mpfr_expr",
}
检验一个平方根:在 53 位精度、就近舍入下,:
///|
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")
}
数值以十六进制有效数和二进制指数书写:0x10000000000000p-1074 即 。
日常任务
带标志的初等函数
初等函数行依次给出函数名、输出精度与舍入模式、操作数、预期结果,以及三个异常标志(不精确、无效、除以零)。未使用的操作数写作 -(第二操作数)和 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 行把每个数拆分为系数、二进制指数和符号:
///|
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")
}
各字段依次为:精度、舍入模式、输入系数(十六进制数字)、输入指数、输入符号(1 表示负)、整数指数、预期系数、预期指数、预期符号、不精确标志。此处 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将固定版本的 MPFRtests/data/sqrt文件、仓库中提交的初等函数矩阵testdata/bin_float/mpfr-4.2.2-elementary.txt与 TestFloat 一起执行;参见验证。初等函数数据和幂运算数据的生成器分别是tools/generate_mpfr_elementary_oracle.c和tools/generate_mpfr_pow_oracle.c。 - 用哪个解析器? 当文件包含
mpfr-elementary-v1时,CLI 选择初等函数格式;包含input_coefficient_hex时选择幂运算格式;否则选择平方根格式。请把标记放在注释行中。
常见陷阱
- 初等函数行比较的是数值而非编码。 在这里
+0与-0相等,任何 NaN 都与预期的nan匹配。平方根行和幂运算行则比较整个BinFloat,包括零的符号。 - 不检查平方根的标志。
sqrt数据行只比较值。 - 没有指数范围。 各行在无界上下文中执行:不存在上溢、下溢或次正规数范围;报告上溢或下溢的初等函数行或幂运算行会失败。
- 二元运算需要第二操作数。 第二操作数为
-的初等函数pow、hypot或atan2行能被解析器接受,但执行时会中止。
后续步骤
- mpfr_expr API:每个条目以及确切的字段布局。
- mpfr_expr 设计:通过规则。
- bin_float 教程:被测试的函数。