frontend/mpfr_expr API

frontend/mpfr_expr 解析用 GNU MPFR 生成的参考数据,并针对 bin_float 执行它。支持三种格式:MPFR 的平方根 data_check 文件、整数幂行,以及带异常标志的初等函数矩阵。该包不进行任何 IO;运行器是 cli/mpfr_expr_cli。工作流程参见教程,通过规则参见设计页面。

在 moon.pkg 中导入该包:

import {
  "Luna-Flow/floating/frontend/mpfr_expr",
}

通用行语法

三个解析器都在 \n 处切分文本,修剪每一行,并跳过空行和以 # 开头的行。字段以空格、制表符或回车符分隔。行号从 1 开始。舍入字段为以下之一

字段BinaryRoundingMode
nRoundTiesToEven
naRoundTiesToAway
zRoundTowardZero
uRoundTowardPositive
dRoundTowardNegative
aRoundAwayFromZero

数值由 @bin_float.BinFloat::from_hex 读取(0x…p…、inf、-inf、nan)。每个解析器在所有行都有效时返回 Ok(document),否则返回 Err,其中每个无效行对应一个 ParseDiagnostic。

平方根数据

parse_sqrt_data

parse_sqrt_data(source, text) 解析由五个字段组成的行:input_precision output_precision rounding input expected。

pub fn parse_sqrt_data(String, String) -> Result[MpfrDocument, Array[ParseDiagnostic]]

输入以 input_precision 位读取,期望值以 output_precision 位读取。行 id 为 sqrt:LINE。

execute_sqrt_data

execute_sqrt_data(document) 为每一行计算 input.sqrt_ctx(ctx),其中 ctx 为 BinaryContext::unbounded(output_precision, rounding~)。

pub fn execute_sqrt_data(MpfrDocument) -> RunSummary

当结果与期望的 BinFloat 相等(==)时该行通过。不比较标志。

MpfrDocument, MpfrCase

MpfrDocument 是一个已解析的平方根文件;MpfrCase 是其中的一行,没有公开方法。

pub struct MpfrDocument {
  // private fields
}
pub fn MpfrDocument::source(Self) -> String
pub fn MpfrDocument::case_count(Self) -> Int

pub struct MpfrCase {
  // private fields
}

source 返回传给解析器的名称,case_count 返回行数。

整数次幂

parse_pow_data

parse_pow_data(source, text) 解析由十个字段组成的行。

pub fn parse_pow_data(String, String) -> Result[MpfrPowDocument, Array[ParseDiagnostic]]

字段为 precision rounding input_coefficient_hex input_exponent2 input_negative exponent expected_coefficient_hex expected_exponent2 expected_negative inexact,其中两个数均为 (−1)negative⋅coefficient⋅2exponent2(-1)^{\text{negative}} \cdot \text{coefficient} \cdot 2^{\text{exponent2}},各符号位和 inexact 为 0 或 1,exponent 是整数幂指数。输入以 512 位读取,期望值以 precision 位读取。行 id 为 pow:LINE。

execute_pow_data

execute_pow_data(document) 计算 input.pow_int_ctx(exponent, ctx),其中 ctx = BinaryContext::unbounded(precision, rounding~)。

pub fn execute_pow_data(MpfrPowDocument) -> RunSummary

当结果与期望值相等(==)、不精确标志等于该行的标志,并且没有引发下溢、上溢、除以零或无效标志时,该行通过。

MpfrPowDocument, MpfrPowCase

MpfrPowDocument 是一个已解析的幂文件;MpfrPowCase 是其中的一行,没有公开方法。

pub struct MpfrPowDocument {
  // private fields
}
pub fn MpfrPowDocument::source(Self) -> String
pub fn MpfrPowDocument::case_count(Self) -> Int

pub struct MpfrPowCase {
  // private fields
}

初等函数

parse_elementary_data

parse_elementary_data(source, text) 解析由十个字段组成的行:op precision rounding x y n expected inexact invalid divbyzero。

pub fn parse_elementary_data(String, String) -> Result[MpfrElementaryDocument, Array[ParseDiagnostic]]

op 为 exp、exp2、exp10、expm1、ln、log2、log10、log1p、sqrt、rootn、pown、pow、hypot、sin、cos、tan、sinpi、cospi、tanpi、asin、acos、atan、atan2、sinh、cosh、tanh、asinh、acosh、atanh 之一。x 和 y 是以 512 位读取的操作数(未使用时 y 为 -),n 是 rootn 和 pown 的整数参数,expected 以 precision 位读取,最后三个字段为 0 或 1。行 id 为 op:LINE。

解析器不检查双操作数函数 pow、hypot 和 atan2 是否提供了 y;执行 y = - 的此类行会中止。

execute_elementary_data

execute_elementary_data(document) 在 BinaryContext::unbounded(precision, rounding~) 中,用 BinFloat 对应其运算的 checked 方法 try_*_ctx(对 sqrt 和 pown 则为 sqrt_ctx 和 pown_ctx)对每一行求值。

pub fn execute_elementary_data(MpfrElementaryDocument) -> RunSummary

当结果与期望值比较相等(compare == 0:+0=−0+0 = -0,且任意 NaN 都与任意 NaN 相等)、不精确、无效和除以零标志等于该行的标志,并且既没有引发下溢也没有引发上溢时,该行通过。若某个 try_*_ctx 方法返回 Err(例如认证失败),该行以消息 "certification failure for MPFR differential case" 失败。

MpfrElementaryDocument

MpfrElementaryDocument 是一个已解析的初等函数文件。

pub struct MpfrElementaryDocument {
  // private fields
}
pub fn MpfrElementaryDocument::source(Self) -> String
pub fn MpfrElementaryDocument::case_count(Self) -> Int

诊断与结果

ParseDiagnostic

ParseDiagnostic 是一个无效行。

pub struct ParseDiagnostic {
  // private fields
} derive(Eq, @debug.Debug)
pub fn ParseDiagnostic::source(Self) -> String
pub fn ParseDiagnostic::line(Self) -> Int
pub fn ParseDiagnostic::message(Self) -> String

消息指明问题所在,例如 "MPFR pow row must contain ten fields"、"invalid MPFR pow field" 或 "invalid MPFR elementary expected value"。

CaseResult

CaseResult 是一行的结果。

pub struct CaseResult {
  // private fields
}
pub fn CaseResult::id(Self) -> String
pub fn CaseResult::passed(Self) -> Bool
pub fn CaseResult::message(Self) -> String

通过时消息为空,否则以十六进制显示期望值和实际值(对于幂行和初等函数行,还显示所比较的标志)。

RunSummary

RunSummary 汇总一个文档中的各行。

pub struct RunSummary {
  // private fields
}
pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::success(Self) -> Bool

每一行都会被执行,因此 total=passed+failed\text{total} = \text{passed} + \text{failed};当没有行失败时 success 为真。results 按行序返回结果。

///|
test "mpfr summary" {
  let rows =
    #|53 53 n 0x0p0 0x0p0
    #|53 53 u 0x3p0 0x1bb67ae8584cabp-52
    #|
  let summary = @mpfr_expr.execute_sqrt_data(
    @mpfr_expr.parse_sqrt_data("s", rows).unwrap(),
  )
  inspect(summary.total_cases(), content="2")
  inspect(summary.passed_cases(), content="2")
}

trait 实现

ParseDiagnostic::equal, ParseDiagnostic::not_equal, ParseDiagnostic::to_repr

这些方法比较位置和消息,并为 Debug 渲染诊断。新代码中请使用 ==、!= 和 debug_inspect。

pub fn ParseDiagnostic::equal(Self, Self) -> Bool
pub fn ParseDiagnostic::not_equal(Self, Self) -> Bool
pub fn ParseDiagnostic::to_repr(Self) -> @debug.Repr

完整公共接口

此快照是该包生成的 pkg.generated.mbti。当正文与接口不一致时,以接口为准。

// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/frontend/mpfr_expr"

import {
  "moonbitlang/core/debug",
}

// Values
pub fn execute_elementary_data(MpfrElementaryDocument) -> RunSummary

pub fn execute_pow_data(MpfrPowDocument) -> RunSummary

pub fn execute_sqrt_data(MpfrDocument) -> RunSummary

pub fn parse_elementary_data(String, String) -> Result[MpfrElementaryDocument, Array[ParseDiagnostic]]

pub fn parse_pow_data(String, String) -> Result[MpfrPowDocument, Array[ParseDiagnostic]]

pub fn parse_sqrt_data(String, String) -> Result[MpfrDocument, Array[ParseDiagnostic]]

// Errors

// Types and methods
pub struct CaseResult {
  // private fields
}
pub fn CaseResult::id(Self) -> String
pub fn CaseResult::message(Self) -> String
pub fn CaseResult::passed(Self) -> Bool

pub struct MpfrCase {
  // private fields
}

pub struct MpfrDocument {
  // private fields
}
pub fn MpfrDocument::case_count(Self) -> Int
pub fn MpfrDocument::source(Self) -> String

pub struct MpfrElementaryDocument {
  // private fields
}
pub fn MpfrElementaryDocument::case_count(Self) -> Int
pub fn MpfrElementaryDocument::source(Self) -> String

pub struct MpfrPowCase {
  // private fields
}

pub struct MpfrPowDocument {
  // private fields
}
pub fn MpfrPowDocument::case_count(Self) -> Int
pub fn MpfrPowDocument::source(Self) -> String

pub struct ParseDiagnostic {
  // private fields
} derive(Eq, @debug.Debug)
pub fn ParseDiagnostic::equal(Self, Self) -> Bool
pub fn ParseDiagnostic::line(Self) -> Int
pub fn ParseDiagnostic::message(Self) -> String
pub fn ParseDiagnostic::not_equal(Self, Self) -> Bool
pub fn ParseDiagnostic::source(Self) -> String
pub fn ParseDiagnostic::to_repr(Self) -> @debug.Repr

pub struct RunSummary {
  // private fields
}
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::success(Self) -> Bool
pub fn RunSummary::total_cases(Self) -> Int

// Type aliases

// Traits