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. 不透明结构体指针 所有上下文类型对外均为不透明指针,禁止直接访问或修改内部成员。
  2. 参数不可变约束 精度、位宽、舍入模式等核心参数仅在初始化时设置,初始化后不可修改。
  3. 传递规则 所有运算、初始化、销毁函数必须显式传递上下文作为参数。
  4. 多实例隔离 同一作用域可创建多个上下文实例,类型隔离,不可混用
  5. 生命周期约束
  6. 上下文必须在所有关联对象销毁后才能销毁
  7. 上下文销毁后,关联对象禁止任何操作
  8. 未销毁关联对象直接销毁上下文 → 内存泄漏/未定义行为

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. 输出参数在前 函数(输出, 输入1, 输入2, 上下文(如需要))
  2. const 修饰输入参数
  3. 无返回值,禁止直接返回指针。
  4. 上下文为最后一个参数

标准格式:

// 无限精度
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 基本原则

  1. 谁初始化,谁销毁
  2. 无限精度类型:自动管理内存,无需手动扩容
  3. 有限精度类型:上下文统一管理内存池/缓存

4.2 生命周期顺序

  1. 有上下文对象
  2. 创建上下文
  3. 初始化对象(绑定上下文)
  4. 执行运算
  5. 清空对象
  6. 销毁上下文

  7. 无上下文对象

  8. 初始化对象
  9. 执行运算
  10. 清空对象

违反顺序将导致未定义行为(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标准。