consistency 设计

设计目标

floating 有四个数值核心,其结论相互重叠:二进制值转换为十进制再转换回来必须表示同一个有理数;checked 包装层给出的值必须与核心相同;区间必须包含标量运算的精确结果;所有核心都必须通过同一套 internal 规则进行舍入。每个包自身的测试无法看到其他包。consistency 是写下并执行这些跨包定律的唯一地方。

数学背景

每个核心的每个有限值都表示一个有理数。令 ⟦⋅⟧\llbracket\cdot\rrbracket 将值映射到 Q\mathbb{Q}(由 semantic 实现,以 internal.ExactRat 作为规范形式)。本套件检查的定律有三种形式:

  • 一致性: 对于表示同一输入的包 AA 的值 xx 和包 BB 的值 yy,当两个运算都精确时 ⟦fA(x)⟧=⟦fB(y)⟧\llbracket f_A(x) \rrbracket = \llbracket f_B(y) \rrbracket;否则结果是两个包对同一实数的舍入。
  • 精确预言: 辅助函数或运算等于一个 BigInt 或有理数计算,例如 round_positive_div 对照 ⌊n/d⌋\lfloor n/d \rfloor 加上舍入表,或 digits10 对照十的幂。
  • 包含性: 对于区间运算 FF 和点运算 ff,x∈X⇒f(x)∈F(X)x \in X \Rightarrow f(x) \in F(X),并且包含关系表现为偏序而非全序。

表示层面的定律也会被检查:GDA 结果保持正确的同值类(cohort)、带符号零和 NaN 载荷;交换格式的编码可以逐位往返。

设计决策

仅白盒测试

该包除测试外没有源文件,且只以 for "wbtest" 的方式导入各核心。因此它永远不会成为库构建的一部分,也没有需要维护的 API,但仍然可以使用内部辅助函数。

来自官方语料的固定见证

许多十进制测试使用官方 decTest 套件中的行作为具名见证。它们固定了曾经在不同包之间出现分歧的确切用例,在进程内运行,无需下载语料。

优先使用预言而非预期值

在可能的情况下,测试会独立计算预期结果(使用 BigInt、ExactRat 或 semantic),而不是硬编码输出字符串,这样即使格式化方式改变,定律依然有意义。

正确性 / 不变式

  • 一次通过的运行表明每条所述定律在其见证上成立;这是有限的证据,而不是对所有输入的证明。
  • 测试是确定性的且与目标无关,因此在 native、Wasm 和 JavaScript 上进行的同一次运行检查的是相同的结论。

被否决的替代方案

  • 将跨包测试放入各个包中。 这会在核心之间产生仅用于测试的依赖环。
  • 仅使用基于性质的随机测试。 随机输入很少命中同值类边界和平局情形;固定见证则可以。

边界

  • 没有公共 API,也没有运行时代码。
  • 不使用外部语料(那是符合性前端的职责),也不做性能测量(那是 bench 包的职责)。