LSR 0015 - LAMMP 接口规范
基本信息
- LSR 编号:0015
- 标题:LAMMP 接口规范
- 作者:Jericho Knox
- 状态:草案
- 类型:标准规范类
- 创建日期:06-02-2026
- 归属项目:LAMMP
- 适用范围:LAMMP 库所有标准与非标准 API、数据类型、内存模型、兼容约束等
- 替代文档:无
- 相关文档:无
摘要
本规范定义 LAMMP 的所有公共接口,包含数据类型、上下文系统、函数命名、内存管理、运算规则、错误处理、兼容性约束。 接口设计目标: 1. 高效性:最小化调用开销; 2. 简洁性:接口语义清晰,无冗余设计; 3. 灵活性:支持无限精度/有限精度双类型体系; 4. 可扩展性:预留新类型、新运算、新上下文参数扩展空间; 5. 安全性:上下文隔离、内存安全、类型安全。
本规范不限制底层实现机制,仅约束对外暴露的 API 行为与契约。
1. 上下文系统
1.1 核心设计目标
实现类型安全的泛型设计,隔离不同精度/位宽/舍入模式的计算环境,避免未定义行为。
1.2 上下文约束规则
- 不透明结构体指针 所有上下文类型对外均为不透明指针,禁止直接访问或修改内部成员。
- 参数不可变约束 精度、位宽、舍入模式等核心参数仅在初始化时设置,初始化后不可修改。
- 传递规则 所有运算、初始化、销毁函数必须显式传递上下文作为参数。
- 多实例隔离 同一作用域可创建多个上下文实例,类型隔离,不可混用。
- 生命周期约束
- 上下文必须在所有关联对象销毁后才能销毁
- 上下文销毁后,关联对象禁止任何操作
- 未销毁关联对象直接销毁上下文 → 内存泄漏/未定义行为
1.3 上下文标准 API 模板
// 上下文初始化:指定精度/位宽,返回上下文句柄
XXX_ctx_t XXX_ctx_init(xxxxxx);
// 上下文销毁:必须在所有关联对象销毁后调用
void XXX_ctx_clear(XXX_ctx_t ctx);
// 上下文获取配置(可选扩展)
size_t XXX_ctx_get_precision(XXX_ctx_t ctx);
round_mode_t XXX_ctx_get_rounding(XXX_ctx_t ctx);
1.4 合法/非法示例
// 合法流程
nint_ctx_t ctx1 = nint_ctx_init(20);
nint_ctx_t ctx2 = nint_ctx_init(10);
nint_t val1, val2;
nint_init(val1, ctx1);
nint_init(val2, ctx2);
// 运算必须使用同一上下文
nint_t res;
nint_init(res, ctx1);
nint_add(res, val1, val1, ctx1); // 合法
// 销毁顺序:对象 → 上下文
nint_clear(val1, ctx1);
nint_clear(val2, ctx2);
nint_clear(res, ctx1);
nint_ctx_clear(ctx1);
nint_ctx_clear(ctx2);
// 非法示例(禁止行为)
nint_add(res, val1, val2, ctx2); // 上下文混用
nint_ctx_clear(ctx1); // 先销毁上下文,后销毁对象 → UB
不建议在同一个作用域内创建多个同一类型的上下文,以避免可能的未定义行为。
2. 数据类型规范
LAMMP 类型分为两大体系: - 无限精度类型:使用指针存储,自动扩容; - 有限精度类型:具体精度/位宽取决于设置或依赖上下文。
2.1 有符号整数类型
| 类型名 | 精度属性 | 上下文 | 用途 |
|---|---|---|---|
lmpz_t |
无限精度 | 无 | 通用任意精度有符号整数 |
nint_t |
有限精度 | 有 | 固定位宽有符号整数(高性能批量计算场景) |
2.2 有理数类型
| 类型名 | 精度属性 | 上下文 | 用途 |
|---|---|---|---|
lmpq_t |
无限精度 | 无 | 精确分数/有理数运算 |
2.3 浮点数类型
| 类型名 | 精度属性 | 上下文 | 用途 |
|---|---|---|---|
lmpf_t |
无限精度 | 无 | 通用任意精度浮点数 |
nfloat_t |
有限精度 | 有 | 固定精度高性能浮点数(高性能批量计算场景) |
lmag_t |
无限精度 | 无 | 无符号浮点数(幅值/误差运算) |
liar_t |
无限精度 | (待定) | 区间算术浮点数(绝对误差限计算) |
2.4 多项式类型
| 类型名 | 系数 | 上下文 | 用途 |
|---|---|---|---|
lmpz_poly_t |
整系数 | 无 | 无限精度整系数 |
lmpq_poly_t |
有理数 | 无 | 无限精度有理数多项式 |
lmpf_poly_t |
浮点系数 | 无 | 无限精度浮点系数多项式 |
modn_poly_t |
n的剩余类 | 有 | 有限精度浮点系数多项式 |
其他数据类型待定。
3. 标准函数接口规范
3.1 命名规范
标准接口函数命名基本范式:
[前缀]_[动作]_[对象]
- 前缀:
lmpz/lmpq/lmpf/nint/nfloat/liar... - 动作:
init/clear/add/sub/mul/div/set/to/cmp... - 对象:
lmpz/lmpq/lmpf/nint/nfloat/liar/ui/si/str... ui:无符号整数str:字符串(用于赋值)- ...(其他类型)
示例:
- lmpz_add:无限整数加法
- nfloat_mul:有限浮点数乘法
- nint_set_ui:有限整数赋值
- nint_to_lmpz:有限整数转换为无限整数
- nint_to_lmpf:有限整数转换为无限浮点数
对于复杂的函数,可以自行考虑合理的命名方式,但应基本遵循上述命名规范。
3.2 生命周期函数
四类基本生命周期函数:
- 初始化:init
- 销毁:clear
- 移动:move(源对象相当于被clear)
- 拷贝:copy
生命周期函数的实现不强制要求可重入,即实现时,无需保证可重复初始化或重复销毁。调用方应自行保证不重复调用生命周期函数。
// 初始化对象(绑定上下文)
void lmpz_init(lmpz_t op);
void nint_init(nint_t op, nint_ctx_t ctx);
// 重置/清空对象
void lmpz_clear(lmpz_t op);
void nint_clear(nint_t op, nint_ctx_t ctx);
// 拷贝对象
void lmpz_copy(lmpz_t rop, const lmpz_t op);
void nint_copy(nint_t rop, const nint_t op, nint_ctx_t ctx);
// 移动对象(源对象相当于被clear)
void lmpz_move(lmpz_t rop, lmpz_t op);
void nint_move(nint_t rop, nint_t op, nint_ctx_t ctx);
3.3 运算函数规范
- 输出参数在前
函数(输出, 输入1, 输入2, 上下文(如需要)) - const 修饰输入参数
- 无返回值,禁止直接返回指针。
- 上下文为最后一个参数
标准格式:
// 无限精度
void lmpz_add(lmpz_t rop, const lmpz_t op1, const lmpz_t op2);
// 有限精度
void nint_add(nint_t rop, const nint_t op1, const nint_t op2, nint_ctx_t ctx);
4. 内存管理规范
4.1 基本原则
- 谁初始化,谁销毁
- 无限精度类型:自动管理内存,无需手动扩容
- 有限精度类型:上下文统一管理内存池/缓存
4.2 生命周期顺序
- 有上下文对象:
- 创建上下文
- 初始化对象(绑定上下文)
- 执行运算
- 清空对象
-
销毁上下文
-
无上下文对象:
- 初始化对象
- 执行运算
- 清空对象
违反顺序将导致未定义行为(UB)。
5. 错误与异常处理规范
LAMMP仅保留最低限度的错误检查,绝大多数错误处理机制都应在Release模式下不发生,这是为了追求绝对的效率。同时,错误或异常只抛出,不处理。错误处理机制应由调用方自行实现。
6. 编码示例
仅作为参考,实际代码应根据具体实现进行调整。
#include "lammp/lmpz.h"
int main() {
// 初始化全局环境建议在进程或线程创建时调用
lmmp_global_init(); // 初始化全局环境
lmpz_t a, b, c;
// 初始化
lmpz_init(a);
lmpz_init(b);
lmpz_init(c);
// 赋值
lmpz_set_ui(a, 1000);
lmpz_set_ui(b, 2000);
// 运算
lmpz_add(c, a, b); // c = a + b
// 输出/使用
// ...
// 销毁
lmpz_clear(a);
lmpz_clear(b);
lmpz_clear(c);
lmmp_global_clear(); // 清理全局环境
return 0;
}
#include "lammp/nint.h"
int main() {
// 初始化全局环境建议在进程或线程创建时调用
lmmp_global_init(); // 初始化全局环境
// 创建上下文
nint_ctx_t ctx = nint_ctx_init(32); // 32 limb 精度
nint_t a, b, c;
// 初始化对象
nint_init(a, ctx);
nint_init(b, ctx);
nint_init(c, ctx);
// 赋值与运算
nint_set_ui(a, 12345, ctx);
nint_set_ui(b, 67890, ctx);
nint_add(c, a, b, ctx);
// 销毁
nint_clear(a, ctx);
nint_clear(b, ctx);
nint_clear(c, ctx);
nint_ctx_clear(ctx);
lmmp_global_clear(); // 清理全局环境
return 0;
}
7. 接口兼容性约束
LAMMP 暴露的接口有标准接口和非标准接口,标准接口应尽可能保持兼容性,但不作为强制约束。非标准接口通常以 XXX_ 命名(结尾以下划线收尾),标准接口则需满足标准接口函数的命名规范。
其他要求如下: 1. 应尽可能避免删除标准接口; 2. 为提高可拓展性和开发自由度,应尽可能暴露非标准接口; 3. 非标准接口可以更加灵活,以运行效率作为第一优先级,而非兼容性; 4. 所有接口应至少兼容C11标准,同时可以兼容C++11标准。