跳到主要内容
未列出页
此页面未列出。搜索引擎不会对其索引,只有拥有直接链接的用户才能访问。

数值函数的形式化验证与参考实现:想法、评估与约束

综合自 idea/ 中的多份讨论:[[PureLibm-rs.md]] 的项目设计、[[项目诊断.md]] 的项目 B 评估与手工艺候选分析、[[Rust科学计算生态调研.md]] 的 LLVM/浮点约束章节、[[项目选择判据-双视角.md]] 的判据框架、[[个人项目选择规则.md]] 的数学库规则。

整理日期:2026年6月


〇、更新后的目标定位(基于 PureLibm-rs 设计)

参考 [[PureLibm-rs.md]] 的设计方案。

PureLibm-rs 是一个以可读性正确性为首要目标的正确舍入(correctly rounded)数学库,使用 Rust 编写。

四项核心原则

#原则含义
1参考实现代码贴近算法的数学表达形式。不做混淆性的位优化。优先使用语义化操作和具名 helper 而非魔法常量。目标读者是"想理解算法的人",不只是"想跑结果的人"
2详细文档每个函数带完整的算法描述(特殊值处理 → range reduction → 多项式逼近 → reconstruction)、交叉引用(论文、CORE-MATH 源码行、标准文档)、系数来源标注
3魔术参数均有出处每个魔法常数标注生成脚本(Sollya/Gappa)、生成命令、脚本路径。脚本放在 coeff/ 目录下,有 Sollya 环境即可复现
4完备的测试五级验证体系:L0 类型系统 + lint → L1 穷举/随机/边界测试 + 高精度 oracle → L2 Kani bounded model checking → L3 Sollya/Gappa 证明 → L4 Coq/Flocq 完整证明

与之前"形式化验证数学库"想法的关系

之前的想法聚焦在验证(证明一个已有实现的正确性)。PureLibm-rs 的设计将范围扩展为先做参考实现,再做验证

  • 实现本身是可读的、像论文公式的代码(手工艺的"手表匠"体验)
  • 验证嵌入实现的全流程——每个阶段的保证强度递进
  • 文档和系数追溯本身就是"领域知识结构化"的产出

这对"形式化验证作为项目"的评估产生了关键影响: 之前认为这个项目在手工艺维度上不好(证明搜索反心流),但 PureLibm-rs 的模式将**"实现 + 文档 + 测试工程"作为手艺活的主体**,形式化验证作为渐进的增强层——实现和工程测试在你可预测推进的那一侧,形式化证明在"偶尔突破"那一侧。


一、核心问题

目标: 构建一个可读、可验证、正确舍入的数学库参考实现——代码本身是审美对象,文档让魔术参数可追溯,验证体系是渐进的分层保证。

动机:

  • AI 让代码生成趋近免费 → 验证需求随之爆发。"可读的参考实现"本身就是 AI 时代的高价值资产(规格优于代码)
  • 数值计算正确性验证是 PSE/科学计算的核心痛点
  • 形式化验证是 AI 最不擅长的硬骨头之一(≥ 5 年窗口期)
  • 已有经验基础:C/F77 数学库维护经验、PureLibm.jl 的可读化中文文档实践

关键前提: 在动手之前,需要理解两件事:

  1. PureLibm-rs 模式如何改变了"形式化验证数学库"的项目体验——实现 + 文档 + 工程测试作为手艺主体,形式化证明作为增强
  2. 目标语言(Rust/LLVM)对浮点运算的底层约束——这决定了"能证明什么"和"在什么假设下证明"

二、项目评估:AI 辅助形式化验证数学库

2.1 战略价值视角

以下来自项目诊断初评(AI 时代竞争力角度)。

判据结果
产出属性形式化规格 + 证明 + 验证方法论 → 纯判断型资产
AI 替代期限≥ 5 年,形式化验证的 proof engineering 是 AI 最不擅长的硬骨头 → 通过
裁员测试代码可擦除重写,但证明、规格、方法论不会消失 → 通过
AI 时代需求趋势显著增强 —— AI 生成的数值代码越多,验证需求越大

潜在可积累资产:

资产类型不可替代性
形式化规格(函数的正确性定义)✅ 核心护城河
证明库(已完成的证明可被引用)✅ 判断型资产
AI 辅助验证的方法论/工作流✅ 知识型资产("最后一公里"经验模式化)
测试集/反例库✅ 边界 case 积累

个人匹配度:

  • ✅ 数学库实现经验(维护过 C/F77 数学库),理解数值计算陷阱
  • ✅ ChemE 领域数值计算需求是独特应用视角
  • ✅ 即使验证不成,方法论笔记本身就有价值
  • ⚠️ 与毕业/研究主线无直接关联 → P2(允许启动,但非最高优先级)

关键风险: 形式化验证 + 数学库,两个都是深坑,必须设边界防无限考古。


2.2 手工艺(Craft)视角重评

以下来自后续的手工艺视角重评。

手工艺项目的评估标准:

维度
心流潜力重复但有技巧,能进入心流高风险阻塞(卡一个问题一整天)
工作单元自包含,做完一个是一个互相依赖,必须整体推进
进度可见做一点就能看到结果长期看不到进展
深度可以深挖,但不强制浅尝辄止或必须深挖
审美回报结果本身就是审美对象只有跑通/没跑通两种状态
维护负担产出静止,不需要持续维护依赖上游,版本漂移
AI 关系AI 可辅助也可不用,不影响体验AI 替代了核心乐趣

形式化验证数学库按上述标准重评:

维度评价说明
心流潜力⚠️ 中偏低证明搜索经常卡死——一个 lemma 卡几小时是常态。不是"重复有技巧",是"困在迷宫里"。心流需要的是可预测的挑战,证明不是
工作单元✅ 好每个函数自包含
进度可见❌ 差典型困境:3 小时看起来什么都没产出。要么证明通过了(瞬间),要么卡着(很久)
深度✅ 好无限深
审美回报⚠️ 中证明通过的瞬间有满足感,但证明本身不是审美对象(除非你是逻辑学家)
维护负担✅ 低证明不需要维护
AI 关系⚠️ 微妙AI 削弱了这个项目的核心乐趣。前 AI 时代手工实现数学库 + 形式化验证是完整的手工艺体验;现在 AI 能生成代码,只剩下证明部分,而证明恰好是卡住/阻塞风险最高的部分

重评结论:作为手工艺项目,形式化验证数学库有结构性缺陷。

核心问题不是做不做得好,而是证明搜索的随机阻塞特性天然反心流。它更像"解谜"(puzzle)而非"手艺"(craft)。解谜的乐趣在于偶尔的突破,手艺的乐趣在于持续的打磨。

前 AI 时代它是好选择,因为"写代码"这层手艺活填充了证明搜索之间的等待。现在这层被 AI 剥离了,剩下的证明部分太硬、太脆,不适合放松。


2.3 PureLibm-rs 模式如何修复这个问题

PureLibm-rs 的设计将工作主体从"纯证明"切换到"实现 + 文档 + 工程测试 + 渐进验证":

之前的模式:
实现(AI 已替代)→ 证明(反心流,阻塞频繁)→ 结束
手艺体验总量:低

PureLibm-rs 模式:
实现(古法手写,审美对象)→ 文档(叙事产出)→ 工程测试(立即可见,心流好)
→ 系数追溯(考古乐趣)→ L0-L2 验证(可预测推进)→ L3-L4 证明(偶尔的深度)
手艺体验总量:高

对手工艺重评的修正:

维度之前(纯验证)PureLibm-rs 模式下
心流潜力⚠️ 中偏低✅ 实现+测试是可预测挑战,证明是可选的深度
进度可见❌ 差✅ 每完成一个函数的实现+测试+文档就是可见进度
审美回报⚠️ 中✅ 代码本身(数学公式的翻译)是审美对象;测试通过的绿色是审美回报;系数来源的考古故事是审美产出
AI 关系⚠️ AI 替代了代码层的乐趣✅ 古法手写实现 + AI 辅助验证 = 各取所需

修正结论:PureLibm-rs 模式将一个"解谜型"项目转化为"手艺 + 解谜"混合项目。 实现和工程测试层提供可预测的心流(手艺满足),形式化验证层提供偶尔的深度突破(解谜满足)。两者加起来,总体验质量显著优于纯验证。

这恰好对应"特殊函数手表匠"的方向——每个函数是一个自包含的机芯,实现它、测试它、记录它的系数来源,本身就是手艺活。形式化验证是"加上去的保险",不是"唯一的产出"。

两个评价的分层:

  • 在"AI 时代战略项目"框架下 → 仍然高价值 ✅
  • 在"手工艺放松项目"框架下 → PureLibm-rs 模式下修复了之前的缺陷,变成了可行的选择 ✅

2.4 建议的启动方式(更新:基于 PureLibm-rs Pilot 阶段)

对应 [[PureLibm-rs.md]] 的 M1–M2 里程碑。

第一步:搭建基础设施(M1),而非直接写证明。

选择 2-3 个 pilot 函数完成全链路验证:

函数复杂度验证价值
cr_sqrtf — 分支少,range reduction 简单验证基础设施:FFI 对接、测试编排、coverage 工具链
cr_sinf — 复杂 range reduction(Payne-Hanek)、多项式逼近、多条件分支验证核心翻译流程 + L2 Kani 验证方案
cr_expf中高 — 特殊值路径多(overflow/denormal)补充异常路径覆盖

交付物:

  • 实现代码 + 函数文档(含系数来源标注)
  • f32 穷举测试通过(对比高精度 oracle)
  • CORE-MATH 一致性测试通过
  • Kani 验证对 cr_sinf 的 range reduction 代码无 panic 和溢出
  • 系数脚本在 coeff/ 下可独立运行

Pilot 阶段通过后,可以复用基础设施推进 M3(全部 ~40 个 binary32 函数)。pilot 不代表其余函数可以机械填充——每个函数仍需要独立确认特殊值策略、hard-to-round cases、系数来源、range reduction 边界和 oracle 差异。


三、参考实现的设计要求

对应 [[PureLibm-rs.md]] 第 1、5 章。

3.1 代码可读性

代码贴近算法的数学表达形式。每个函数遵循统一的结构模板:

/// 函数名 + 简短描述
///
/// # 正确性保证
/// - 正确性 oracle: MPFR / 高精度参考,f32 穷举测试已通过
/// - 翻译一致性参考: CORE-MATH (commit hash)
///
/// # 算法描述
/// 1. 特殊值处理(NaN, Inf, subnormal)
/// 2. Range reduction 步骤
/// 3. 多项式逼近
/// 4. Reconstruction
///
/// # 系数来源
/// Sollya 脚本: `coeff/sinf.sollya`
///
/// # 验证
/// - Kani: `verification/sinf_range_reduction.rs` 验证 range reduction
/// - f32 穷举测试: `cargo test --features exhaustive --test exhaust sinf`
pub fn cr_sinf(x: f32) -> f32 { ... }

3.2 位操作策略

不鼓励推荐
为普通数值操作内联 bits & 0x7fffffff 取绝对值优先使用 f32::abs(x);需要保留 NaN payload 时用具名 helper
为普通数值操作内联 bits ^ 0x80000000 翻转符号优先使用 -xcopysign(x, y)
memcpy / 类型双关转换f32::to_bits() / f32::from_bits()

对于 IEEE 754 编码层面的提取操作,应封装为具名函数:

// 不鼓励:每次使用时都需要理解位运算含义
let bits = x.to_bits();
let exp = ((bits >> 23) & 0xff) as i32;

// 鼓励:抽象为具名函数
fn extract_exponent(x: f32) -> i32 { ... }

3.3 架构决策

问题决策
no_std起步阶段以 std 为默认,核心算法与 I/O/FFI 分离以保留未来提取路径
C FFI 绑定暂不考虑。后续如有需要以独立包形式提供
fenv/errnoAPI 合同只保证返回值。在不影响可读性的前提下尽可能保持与 C libm 的返回值语义一致(signed zero、NaN、Inf、subnormal)
FMA 使用使用 f32::mul_add / f64::mul_add 表达 FMA 语义;不要求硬件 FMA 指令
命名前缀公开 API 使用 cr_ 前缀(如 cr_sinf);常量使用 CR_ 前缀
MSRVRust 1.85(Edition 2024)

四、魔术参数的出处追溯

对应 [[PureLibm-rs.md]] 第 5 章可读性要求。

这是 PureLibm-rs 区别于普通 libm 实现的核心特征:每个魔法常数都能回答"这个数字是怎么来的"。

4.1 系数标注格式

源码中每个魔法常数必须标注来源:

// Generated by: Sollya
// Script: coeff/sinf.sollya
// Command: remez(..., [-2^-12, 2^-12], ...)
const CR_SINF_A: f64 = 0x1.921fb54442d17p-3;

4.2 系数脚本目录

coeff/ 目录下提供可独立运行的 .sollya 脚本:

# 有 Sollya 环境即可复现
sollya coeff/sinf.sollya

脚本注释中标注使用的 Sollya/Gappa/MPFR 版本。在函数集完全实现后,再考虑多版本交叉验证。

4.3 引用文献

函数文档应交叉引用相关论文和 CORE-MATH 源码行:

//! # References
//! - [CORE-MATH sinf.c (commit a1b2c3d)](https://github.com/...)
//! - J.-M. Muller, "Elementary Functions: Algorithms and Implementation", 3rd ed.
//! - Payne & Hanek, "Radian Reduction for Trigonometric Functions", 1983

4.4 为什么这很重要

在 AI 时代,规格就是护城河。一个包含完整系数来源、算法描述和引用链的参考实现,其价值远超一个"能跑但不知道为什么"的实现。系数追溯文档本身是"领域知识结构化"的产出——把论文和脚本里的隐式知识变成可复现的公共品。


五、完备的测试体系(五级验证)

对应 [[PureLibm-rs.md]] 第 2 章。

验证分为五个级别,每一级提供不同强度的保证:

级别手段保证内容CI 频率
L0Rust 类型系统 + #[deny(unsafe_op_in_unsafe_fn)] + clippy lint + 单元/集成测试降低 UB、panic 风险;禁止新增未审查的 panic!unwrap、越界索引每次提交
L1float32 穷举测试 + float64 随机/边界测试。正确性 oracle 使用高精度参考(MPFR);翻译一致性 oracle 使用 CORE-MATH FFIf32 在穷举输入上符合正确舍入目标;f64 在采样范围内与参考一致穷举为 nightly/cron,其余每次提交
L2Kani bounded model checking对 range reduction、整数/位操作、表索引等逻辑验证无 panic、无越界、无未声明溢出每次提交
L3Sollya + Gappa 脚本生成多项式逼近的误差边界证明;计算公式常数记录在 coeff/,手工检查
L4Coq / Flocq完整机器可检查的正确舍入证明CORE-MATH 已有部分函数完成,本项逐步对接

项目起步瞄准 L0–L2。L3–L4 作为文档和演进目标。

Oracle 分层

  1. 正确性 oracle:用于证明正确舍入目标。对比 MPFR 或其他高精度参考,按目标舍入模式生成期望结果。
  2. 翻译一致性 oracle:用于证明 Rust 移植没有偏离指定 CORE-MATH commit。CORE-MATH 以 git submodule 形式纳入,build.rs 通过 cc crate 编译为静态库,测试中 FFI 调用。

CORE-MATH 一致性测试不能单独证明正确舍入;它只证明与指定参考实现返回值一致。若 CORE-MATH 和高精度 oracle 结果冲突,以正确性 oracle 为准。

测试组织

src/ ← 库代码
tests/ ← cargo test: 随机 + 边界值测试(每次 CI)
tests/exhaust.rs ← #[cfg(feature = "exhaustive")] gate(nightly cron)
tests/exhaust/ ← 穷举测试子模块
kani.toml ← cargo kani harness 注册
verification/ ← Kani 验证代码,只通过 #[cfg(kani)] 编译

六、相关手艺项目方向

PureLibm-rs 的模式(实现 + 文档 + 工程测试 + 渐进验证)恰好将"特殊函数手表匠"的手艺体验和"形式化验证"战略价值结合为一个统一的工作流。以下是形成互补的三个相关方向。

每次选一个数学函数(erf, log1p, hypot, tgamma, j0...),深入研究它、实现它、测试它、记录它。

手工艺优势:

  • 每个函数自包含:读原始论文 → 选算法 → 实现 → 跑误差测试 → 画误差曲面图 → 写笔记
  • AI 拿不走手艺乐趣:AI 可以生成实现,但不能替你欣赏 1969 年 Cody 的方法和 1993 年 Tang 的近似哪种更优雅
  • 维护负担 ≈ 零
  • 长期性:C99 有 100+ 个数学函数,加上 IEEE 754-2019 新增的,够做好几年

与 PureLibm-rs 的关系: 这是 PureLibm-rs 的"手艺核心"——你可直接在这个项目中实践:选一个 CORE-MATH 未覆盖的函数 → 古法手写实现 → 写文档 → 跑穷举测试 → 标注系数来源。PureLibm-rs 的工程结构可以复用。


6.2 浮点陷阱图鉴(FP Trap Encyclopedia)

系统地收集、复现、解释、可视化浮点数陷阱——那些让数值程序悄然出错的情况。

手工艺优势:

  • "田野调查"模式:发现案例 → 最小化复现 → 理解机制 → 画图解释 → 归档
  • 审美产出很好:精心设计的浮点陷阱可视化本身就是作品
  • AI 只能生成"已知的"陷阱,不能真正跑代码发现新案例
  • 长期性:无限

与形式化验证的关系: 浮点陷阱图鉴收集的反例,可以作为形式化验证的测试集——两者互补。一个做"正面证明",一个做"反面探测"。


6.3 FORTRAN 遗产修复(Legacy FORTRAN Restoration)

选取 netlib、SLATEC 等经典 FORTRAN 数值库中的子程序,做"考古修复"——理解、翻译到现代语言(Julia)、补测试、写历史注释。

手工艺优势:

  • 像修复古籍——每段代码背后有作者的经验、时代假设、未写出的推导
  • AI 可以翻译代码,但 AI 不能做"考古"——理解为什么 1979 年的作者用了这个奇怪的常数
  • 审美对象是翻译的优雅程度

关键约束: 这是一次性的翻译+注释产出,不是持续维护原库。只做前者。


6.4 方向间的互补关系

特殊函数手表匠 ←→ 浮点陷阱图鉴 ←→ PureLibm-rs 验证体系
正向建造 反向探测 分层正确性保证
"造表" "田野调查" "证明 + 保险"

PureLibm-rs 把这些方向整合为统一工作流:
手表匠 = 实现层(手写 + 文档 + 系数标注)
陷阱图鉴 = 测试输入源(反例纳入 CI 测试集)
验证体系 = L0-L4 分层保证(工程测试 → 形式化证明)

三者共享底层的数学函数知识。PureLibm-rs 提供了将它们统一在一起的工程框架。


七、LLVM 对浮点运算的弱约束

以下来自 Rust 科学计算生态调研第八章。

在考虑用 Rust 做形式化验证或高精度数值函数实现时,必须理解 Rust/LLVM 浮点运算的底层约束——这决定了"能证明什么"和"在什么假设下证明"。Rust 通过 LLVM 生成机器码,LLVM 的浮点 IR 指令并非严格 IEEE 754,在多个维度上提供了弱于 C 编译环境的保证。


7.1 舍入模式:LLVM 评级 F(完全未实现)

能力C (gcc/clang + glibc/musl)Rust (via LLVM)
动态舍入模式fesetround(FE_UPWARD) via fenv.h不可用。修改 MXCSR/FPCR 是 UB
静态舍入操作#pragma STDC FENV_ROUND (C23)LLVM 评级 F — 完全未实现
约束 intrinsic存在 llvm.experimental.constrained.*,但 Rust 不暴露

实际后果: 如果你想实现一个需要非默认舍入的数值函数(如 interval arithmetic 需要向上/向下舍入),Rust/LLVM 原生不支持。唯一的 workaround 是:

  • unsafe + inline asm 操作 MXCSR(跨平台不兼容且是 UB)
  • 依赖 fesetround 的 FFI 绑定(不可移植,优化器可能破坏)
  • 使用整数位操作模拟不同舍入方向的运算

7.2 NaN 传播:故意非确定性

Rust RFC 3514(2024 稳定化)明确规定:

  • NaN 的符号和 payload 不是确定性的 — 相同的操作、相同的输入,在不同架构、优化级别甚至不同运行之间,可能产生不同的 NaN 位模式
  • const fn 和运行时求值可能产生不同的 NaN — 这在 Rust 1.82 中被正式稳定化
  • sNaN 可以传播为 sNaN — 违反 IEEE 754 的"操作从不输出 sNaN"规则(LLVM 优化如 x * 1.0 → x 需要这个行为来保持语义)

这意味着:你不能在 Rust 中验证 NaN 传播的精确行为,因为规范本身不承诺。如果需要"当输入是 NaN 时输出特定的 NaN payload"(某些嵌入式或安全关键场景),Rust 不是正确的工具。


7.3 浮点环境:没有暴露

C 能力Rust 状态
fetestexcept(FE_OVERFLOW)不可用
feclearexcept(FE_ALL_EXCEPT)不可用
fegetenv / fesetenv不可用
#pragma STDC FENV_ACCESS ON不存在

实际后果: 如果你的数值函数需要"检测是否发生了溢出/下溢/不精确"作为算法分支条件(某些自适应精度算法中常见),Rust 不直接支持。


7.4 精度收缩

行为C(fp-contractRust
FMA 自动收缩实现定义,#pragma STDC FP_CONTRACT 控制*+ 相邻时默认允许收缩。设置 -C target-feature=-fma 可禁用

a * b + c 在 Rust 中可能被优化为 fma(a, b, c)(一次舍入)或保留两次舍入——不承诺具体行为。需要严格 bitwise 可复现的场景需要用 mul_add 显式控制。


7.5 已知不兼容 IEEE 的平台

平台问题
32-bit x86 无 SSE2 (i586)x87 80-bit 内部精度,无法提供 IEEE 兼容结果
32-bit x86 有 SSE2x87 返回寄存器可能修改 NaN payload
旧 MIPSquiet/signaling bit 反了
32-bit ARM NEONSIMD 操作总是 flush-to-zero

八、Rust libm vs C libm

8.1 Rust libm 的优势

Rust 的 libm crate(从 musl 移植)有比 C 生态更现代的测试基础设施:

特征说明
ULP 精度框架每个函数有明确的 ULP 误差阈值(标准数学函数 0-4 ULPs)
MPFR 参考验证CI 中以高精度 MPFR 库为 golden reference
边界 case 框架显式的 EdgeCases 生成器,覆盖 ±0、±∞、NaN、渐近线、临界点
跨架构测试自动检测跨平台一致性
可覆盖容忍度MaybeOverride trait 允许标记已知问题的断言失败/ULP 放宽/跳过

一篇 2025 年的研究(Gladman et al.)直接比较了双精度 cosh 的最大 ULP 误差:

最大 ULP 误差
musl1.04
OpenLibm / FreeBSD1.47
GNU glibc1.93
Newlib2.67

musl(和继承它的 Rust libm)在精度上可以超过 glibc


8.2 Rust libm 的弱项

弱项说明
NaN 行为取决于编译目标非确定性来源于 LLVM 后端,不是 libm 代码的问题,但结果一样
交叉架构一致性弱于严格 CC 有 #pragma STDC FENV_ACCESS 来约束优化器;Rust/LLVM 没有等价机制
sNaN 处理分歧Rust libm 继承了 musl 的 C 标准立场(pow(sNaN,0)=1),glibc 的立场是返回 NaN。这种分歧在不同标准的解读之间无法消除
Rust 版本升级可能改变浮点行为const fn 浮点运算的行为在 1.82 改变过;未来 LLVM 升级可能改变 runtime 路径上的优化

九、形式化验证工具现状

工具方法浮点能力状态
Kani模型检查(CBMC 后端)v0.59-0.61 增强了浮点支持,可以验证固定输入范围的精度断言。不支持舍入模式/NaN propagation 的验证对数学函数验证仍然有限
Creusot演绎验证(Why3 后端)专注于 Rust 的类型安全和借用语义。浮点专用 support 较弱不适合纯数值验证
Verus演绎验证(SMT via Z3)通过 Rust 的 assert! 和 proof 函数验证。浮点公式在 SMT 中是理论难点可用于辅助证明算法逻辑,而非精度
grug基于 MIR 的符号执行研究级,可以探索浮点路径早期

现状:没有一个 Rust 工具可以端到端验证"这个函数对所有 f64 输入的误差 ≤ 1 ULP"。 这是一个开放的研究问题——部分因为 LLVM 的非确定性 NaN 语义使得验证的 precondition 本身就很难写。


十、对项目的实际含义

10.1 在 Rust 中,你能可靠验证什么?

可验证方法局限
✅ 固定输入输出的 bitwise 等价Kani + property test需要固定编译目标
✅ 给定输入的 ULP 误差界限proptest + MPFR 对照非形式化证明
✅ 不 panic、不溢出、不除零Kani + #[kani::proof]不含浮点域约束
⚠️ 单调性proptest + 采样全输入域的单调性是开放问题
❌ NaN propagation 行为Rust 不承诺确定性
❌ 跨所有浮点输入的 ≤ 1 ULP 保证无现成工具,需手动证明

10.2 证明声明中必须包含的假设

如果你要做"形式化验证"(即使是部分验证),文档开头必须声明:

  1. 目标硬件平台(如 x86_64-unknown-linux-gnu,禁止 i586)
  2. 接受的 NaN 行为(接受非确定性,仅验证非 NaN 输入路径)
  3. 舍入模式假设(默认 round-to-nearest-even,不验证其他模式)
  4. 验收标准(对 f64 所有非 NaN 输入,误差 ≤ 2 ULPs)

10.3 核心结论

在 Rust 中做数值函数的形式化验证,其理论完备性弱于 C + #pragma STDC FENV_ACCESS 组合。但 Rust libm 的测试基础设施比大多数 C libm 的实际测试更系统。

换句话说:C 的标准环境理论上提供更强的浮点确定性(你可以用 fenv.h 告诉编译器不要越界),但实践中大多数 C libm 实现并没有 Rust libm 那种 ULP 精度框架和跨架构 CI。理论完整性和工程验证强度之间存在一个值得注意的 trade-off。


十一、替代方案

如果有追求最高浮点确定性的需求:

方案说明代价
C + #pragma STDC FENV_ACCESS ON编译器不得跨浮点操作优化C 语言本身的内存安全风险
Julia可以调用 llvmcall 加 constrained intrinsic,且 Base.Math 已是黄金参考仍然依赖 LLVM 后端
直接在 Julia 中验证算法,在 Rust 中做工程实现形式化规格用 Julia 标注,Rust 实现用 proptest + MPFR 对抗两个语言的验证结果需要对齐
Ada (SPARK)SPARK 的浮点合约是工业级最强的,有静态精度证明生态窄,不实用
Rust + 软件浮点库soft-float crate 做 bit-exact 跨平台计算极慢,不适合日常使用

十二、C libm vs Rust libm:综合评价矩阵

维度C libm 生态Rust libm 生态对验证工作的影响
标准环境浮点确定性⭐⭐⭐⭐ (有 fenv)⭐⭐ (LLVM 约束弱)C 更强
工程测试基础设施⭐⭐½ (ad-hoc)⭐⭐⭐⭐ (ULP 框架 + MPFR CI)Rust 更强
NaN 确定性⭐⭐⭐½⭐ (故意非确定)C 大幅领先
舍入模式控制⭐⭐⭐⭐⭐ (基本没有)C 大幅领先
跨架构一致性⭐⭐½ (取决于编译器)⭐⭐½ (同样取决于 LLVM)持平
形式化验证工具⭐⭐⭐ (Frama-C, VST)⭐⭐ (Kani, Creusot)C 更成熟
AI 辅助验证友好度⭐⭐ (UB 多)⭐⭐⭐⭐ (类型安全)Rust 更好

十三、项目选择判据框架的交叉应用

13.1 形式化验证在判据框架中的位置

价值判据("判断"还是"代码"?):

  • 形式化规格 + 证明 → 纯判断型资产
  • AI 替代期限 → ≥ 5 年 ✅
  • 裁员测试 → 去掉代码,证明和规格仍有价值 ✅

需求判据(在 AI 时代是增强还是减弱?):

  • 形式化验证需求随 AI 代码量增长而爆发 → 增强

资产判据(不可替代型资产占比):

  • 规格 ✅ | 证明 ✅ | 测试集 ✅ | 方法论 ✅
  • 代码实现 ❌(可被 AI 替代)
  • 比例:高 ✅

在"高价值领域速查"中的位置:

  • 基准与评测 ✅
  • 验证工具链 ✅
  • 领域知识结构化 ✅

13.2 两级过滤器快速判断

过滤器形式化验证数学库
1. AI 做不好,且短期内做不好?✅ 是(≥ 5 年)
2. 去掉代码后 3 年后还有用?✅ 是(证明、规格是长期资产)
3. 积累的资产是"判断"还是"代码"?✅ 判断型
4. 我有别人没有的东西吗?✅ 数学库实现经验 + ChemE 视角

战略角度:通过。手工艺角度:不通过。 关键取决于你要什么。


十四、关于数学库的个人规则

来自 [[个人项目选择规则.md]] 的相关内容。

数学库函数重写

读别人代码并重写的实际成本很高,因为数学库代码通常压缩了:

  • 数值分析、误差控制、table generation
  • 历史 bug fix、特定平台假设
  • 作者经验和未写出的推导

如果没有作者交流、原始推导、测试集和实际使用场景,单纯重写很容易变成无限考古。

以后只有在以下情况下继续:

  • 服务某个具体函数的验证
  • 服务某篇技术文章
  • 服务自己的参考库
  • 服务一个真实 bug 修复
  • 服务简历/研究展示
  • 有明确 benchmark 和完成定义

否则不作为独立长期项目。

特殊函数库 / F77 数学库维护

如果自己实际上不用,默认降级为有限维护:

  • 保持项目可构建
  • 修复明确问题
  • 接受高质量 PR
  • 不主动扩展
  • 不为"它有意义"承担无限责任

数学知识补充既是奖励也是负担,必须和明确需求绑定。


十五、综合行动建议

  1. PureLibm-rs pilot 作为手艺项目主线 → 搭建 M1 基础设施 + 完成 2-3 个 pilot 函数(cr_sqrtf, cr_sinf, cr_expf)。这是"特殊函数手表匠"的实际载体——实现、写文档、标注系数来源、跑穷举测试、跑 Kani。手艺体验好,战略价值高。

  2. 形式化验证作为渐进增强,不是起点 → L0-L2(类型系统 + 穷举测试 + Kani)作为 CI 常驻;L3-L4(Sollya/Coq)作为文档和演进目标,不急。

  3. 浮点陷阱图鉴作为并行项目 → 与 PureLibm-rs 互补。发现的反例可以纳入 PureLibm-rs 的测试集。

  4. 如果追求最高浮点确定性 → 最终的 bit-exact 验证可能需要 C + #pragma STDC FENV_ACCESS 环境。但在那之前,Rust 的测试基础设施完全够做方法论级的工作。

  5. 长期方向 → PureLibm-rs 的系数和文档本身就是"领域知识结构化"的产出。ℜeos/FeOs 的测试贡献是另一个直接的社区出口。

  6. 与 ChemE 的联系 → 面向科学计算的验证工具链,是"个人发展 × 社区贡献"的交集方向之一。PureLibm-rs 在这个方向上的积累——系数追溯、测试体系、形式化方法——都可以迁移到 ChemE 数值模型的验证中。