架构
本指南介绍 luna-poly 各包如何组合在一起:分层、依赖图、各不变量在何处得到保证,以及不可变层与可变层如何共享算法。
分层
luna-poly 分为三层:
- 词汇层:
core定义单项式(ExponentVector)、命名变量(Variable、VariableContext)、形状、能力 trait 和操作记录。它不存储任何多项式。 - 表示层:四个不可变包(
immut/dense、immut/term、immut/sparse、immut/context)及其四个可变对应包实现多项式的存储与算法。 - 门面层:
immut和mutable重新导出词汇层、luna-generic代数 trait 以及各自所在层的表示。
internal 存放模块私有的辅助函数,consistency 只包含测试。
依赖图
luna-generic arithmetic type_theory/core
\ | /
\ | /
core <--+----------+
/ | \
internal / | \
| / | \
immut/dense immut/term immut/sparse
| \ /
| immut/context
| |
mutable/dense mutable/term mutable/sparse
\ \ /
\ mutable/context
\ |
immut (facade) mutable (facade)
\ /
consistency (tests only)
用文字描述:每个表示都依赖 core;不可变表示以及可变的 term 与 sparse 包使用 internal 计算幂;immut/context 建立在 immut/term 和 immut/sparse 之上;每个可变包依赖其不可变对应包;mutable/context 还使用可变的 term 与 sparse 包进行转换;每个门面包依赖其所在层的各包;consistency 仅在测试中依赖两个门面包。PowNatChecked 需要 arithmetic,Name 需要 type_theory/core。
不变量所在位置
| 不变量 | 保证位置 |
|---|---|
| 指数向量没有末尾的零;次数被缓存 | core (ExponentVector::from_array, with_exponent, *) |
| 单项式序是分次单项式序 | core (ExponentVector::compare) |
| 上下文中的名字互不相同;下标 = 位置 | core (VariableContext::extend_checked) |
| 稠密系数没有末尾的零 | immut/dense、mutable/dense(每个构造器和修改操作) |
| 项数组严格降序、已合并、不含零 | immut/term(from_terms 规范化),由 mutable/term 复用 |
| 稀疏映射不含零值 | immut/sparse、mutable/sparse(每次插入) |
| 上下文操作校验变量、重复项和上下文 | immut/context,由 mutable/context 复用 |
各层如何共享代码
可变层直接在其存储上实现原地更新,并通过 to_immut / from_immut 把所有非平凡算法委托给不可变层。mutable/context 是包裹不可变上下文多项式的可变单元。这样 Karatsuba、复合、求导、多变量乘积以及全部上下文逻辑都只有一份实现,并由 consistency 测试检查两层的一致性。
一次代换的数据流
ContextPolynomial::substitute_names 一次性展示了所有层:
- 每个
type_theory的Name通过VariableContext::variable_by_type_theory_name(core)解析为Variable; - 代换列表在
immut/context中进行校验(成员关系、重复项、上下文相等); - 每一项都被改写为各替换值的幂的乘积,使用 term 或 sparse 算术以及
internal.pow_nat; - 部分结果由稀疏表示相加并规范化。
可变版本把其载荷转换为不可变的载荷,执行相同的步骤,再把结果包装起来。
测试
- 每个实现旁边的内联
test块检查与表示相关的行为,包括core中的type_theory名字查找,以及两个上下文包中的命名代换测试。 src/immut/laws_wbtest.mbt用moonbitlang/quickcheck检查代数定律。src/consistency/core_wbtest.mbt检查各层与各表示之间的一致性。
用 moon test 运行全部测试;提交 PR 前的完整步骤见贡献指南。