Sign in

    moonmatbridge

    Native MoonBit recursive MAT Level 5 reader, writer and scientific data bridge

    matlab
    mat
    scientific-data
    interop
    Download zip
    Author
    Version
    0.0.9
    License
    Apache-2.0
    Last updated
    1 hour ago
    Downloads
    15

    #MoonMatBridge v0.0.9

    MoonBit 原生 MAT Level 5 读写与科研数据互操作库。

    MAT 递归 cell/struct/char/legacy object、密集/CSC 稀疏读写、数值编码、zlib/DEFLATE 解压与压缩、JSON/无损快照、NPY 互通和精确差异检查都由 MoonBit 实现。运行核心库和 Windows 命令行程序不需要 MATLAB、Python、SciPy、Node.js 或第三方压缩库。Node.js 仅用于开发脚本与可选 JS 命令行;SciPy/NumPy 仅用作独立兼容性验证。

    当前源码版本为 v0.0.9,发布模块名为 WeiR-h/moonmatbridge。v0.0.3 完成的五轮核心迭代继续保留,详见 迭代记录。v0.0.5 补齐的 cell、struct、char 和 legacy object 递归读写继续提供混合文件与独立验证;最终读写范围与验收终点 明确全部公开基本类 1–15 的交付目标。

    项目定位是把科研数组连同类型、维度、列优先顺序和复数分量一起保留下来,让 MoonBit 项目直接交换 MATLAB/Python 数据。

    • 以 CSC 存储处理大型稀疏矩阵;只有明确调用 densify 才尝试展开,并在分配前检查额度。
    • 用 snapshot / restore 保存原始数值字节、NaN 编码、负零和稀疏容量;普通 JSON 继续用于可读数据交换。
    • 用 diff 按变量名检查内容与存储元数据,定位变化坐标,忽略原文件的头部描述、压缩形式与大小端;退出码可直接作为 CI 门禁。
    • 转换流程支持切片、按轴取样、拼接、整形和轴置换,复制原始字节,保留未处理的稀疏变量。

    这些能力共同服务于可复现的科研文件交换;范围比较与已有项目的交集见 独特性说明。

    本轮执行记录见 v0.0.6—v0.0.9 计划与交付索引,实测结果见 性能方法与报告。自定工程目标与官方验收分别记录。

    v0.0.6 新增 15 个基本类的独立读写矩阵、真实 GNU Octave v6/v7 双向验证入口,以及 同机性能对照方法。运行报告分别记录已经验证的行为和未关闭的兼容缺口。

    v0.0.7 将密集、CSC 与混合树写入统一到预检尺寸的固定缓冲,避免逐层复制;完整输入验证后才分配主要输出。性能结果按宿主与场景分别记录。

    v0.0.8 新增 read_selected、inspect_roots 和 roots 命令;未选变量仍执行完整验证,减少其数据树和负载分配。空选择也不会跳过校验。输入仍整体驻留内存,压缩根变量仍需有界解压。

    v0.0.9 冻结 API,提供 三个完整科研流程 与便携包一键演示,扩大全部基本类的 global 标记交叉验证,并整理 复审技术附件。完整标准变体和 MATLAB 运行仍有未完成项,保持 0.x。

    本轮性能结果保留未达项:v0.0.8 原生选择读取提速约 14.2 倍,峰值下降 38.3%,仍未达到自定 40% 内存目标;JS 对应约 10.3 倍和 48.1%。四组写入目标通过,完整固定场景未发现超过 10% 的退化;原始样本与首轮退化记录均保留。

    #支持范围

    能力v0.0.9
    MAT Level 5 读取小端、大端;标准标签与小数据标签;多变量
    压缩读取miCOMPRESSED;MoonBit 解码 stored/fixed/dynamic DEFLATE,验证 Adler-32
    MAT 写入确定性的未压缩/压缩小端文件,固定创建描述,不嵌入时间戳
    递归混合类型cell、struct 数组、char、legacy object(类名与字段数据);多维、空数组和交叉嵌套
    字符六种存储标签;中文、非 BMP;保留编码及原始存储单位,大小端读取
    CSC 稀疏二维 double、logical、complex double;混合文件、容量保留、显式密集转换
    数值类型float32/64;有符号、无符号 int8/16/32/64;logical
    复数float32、float64 的实部与虚部分开保留
    形状标量 [1,1]、行/列向量、多维和空数组,保持列优先存储
    数据保真同存储类型的 MAT 往返保留原始 IEEE 字节、NaN payload、负零和精确 64 位整数
    JSON 互通moonmatbridge/1 严格字段;64 位整数使用十进制字符串
    NumPy 互通导出 NPY v1.0;读取 NPY 1/2/3,大小端与 C/Fortran 顺序,复数交错编码
    数组处理保留原始字节的切片、按轴取样、拼接、reshape、轴置换;混合文件按名称提取变量
    根目录与按需构造roots / inspect_roots 返回根变量元数据;read_selected 保持请求顺序并验证未选变量
    无损快照严格 JSON + 原始十六进制字节;密集/CSC、NaN 编码、负零、容量与全局标记
    科研差异按变量名比较原始字节与元数据;全局样本额度、坐标、实/虚部计数和 CI 退出码
    核心编译目标JS、wasm-gc、native 已验证
    命令行Windows x64 原生 EXE;可选 Node.js 文件适配器

    **明确边界:**当前不支持 MATLAB 私有对象扩展(MCOS/opaque)、函数句柄、子系统 workspace、MAT v4、HDF5 MAT v7.3、复数整数、流式读取;NPY 的 object/pickle、结构化、字符串、float16、datetime、NPZ 和含义不明确的 native-endian 描述符。CSC 仅支持 double/logical/complex double;活动行索引必须在每列严格递增,重复或乱序返回错误。info/roundtrip/compress/select 使用完整混合树;JSON、NPY、变换、快照和 diff 保持原数值/CSC 输入域。遇到不支持的类别会返回错误,不会静默丢掉变量。变量名限非空 UTF-8,避免 NUL;非 UTF-8 旧名称不在此版支持范围内。MAT 类型与存储类型不同的密集文件会按声明类型恢复,拒绝无法安全转换的值。

    混合类型案例:三个可下载 MAT 文件及复现步骤,含 13 个根变量及嵌套 cell/struct/char/CSC,保留精确 uint64、复数和 legacy 类名。真实 GNU Octave 流程由 CI 执行,实际结果见各版 verification/reports/octave-v*.json;MATLAB 执行尚无回执,兼容缺口见读写矩阵。

    #直接运行 Windows 程序

    从 GitHub Releases 下载并解压对应版本的 windows-x64.zip,在解压目录打开 PowerShell:

    .\moonmat.exe version .\moonmat.exe sample sample.mat .\moonmat.exe info sample.mat .\moonmat.exe roots sample.mat .\moonmat.exe dump sample.mat sample.json .\moonmat.exe pack sample.json from-json.mat .\moonmat.exe npy sample.mat temperature temperature.npy .\moonmat.exe from-npy temperature.npy temperature from-numpy.mat .\moonmat.exe select sample.mat subset.mat temperature sample_id .\moonmat.exe roundtrip sample.mat copy.mat .\moonmat.exe transform sample.mat examples\transform-plan.json transformed.mat .\moonmat.exe compress transformed.mat compressed.mat .\moonmat.exe snapshot compressed.mat archive.json .\moonmat.exe restore archive.json restored.mat .\moonmat.exe diff compressed.mat restored.mat equality-report.json .\moonmat.exe sparsify sample.mat temperature sparse.mat .\moonmat.exe densify sparse.mat temperature dense.mat

    输出文件必须是新文件;重复路径会报 output-exists,不会覆盖已有数据。正常命令返回 JSON,version、help 返回文字。错误输出到 stderr,退出码为 1。diff 内容相同返回 0,内容变化返回 2,输入或输出错误返回 1;变化是有效比较结果。中文及带空格路径已测试。程序只依赖 Windows 系统自带的 KERNEL32.dll、msvcrt.dll。

    仓库构建后也可以运行:

    node scripts/cli.mjs info sample.mat

    JS 适配器只读写文件;格式处理使用编译后的 MoonBit。

    #MoonBit API

    发布模块名为 WeiR-h/moonmatbridge。在已有 MoonBit 项目中安装:

    moon add WeiR-h/moonmatbridge@0.0.9

    核心代码在 src/,公开接口在 src/pkg.generated.mbti。包内示例可直接运行:

    moon run src/examples/main --target js moon run src/examples/main --target wasm-gc moon run src/examples/main --target native

    消费者的 moon.pkg 导入:

    import {
    "WeiR-h/moonmatbridge" @mat,
    }

    核心调用示例(所在函数声明 raise @mat.MatError):

    let a = @mat.numeric_array(
    "signal", @mat.Float64, [2, 2],
    [Floating(1.0), Floating(2.0), Floating(3.0), Floating(4.0)],
    )
    let bytes = @mat.write_mat([a])
    let file = @mat.read_mat(bytes)
    let restored = file.get("signal").unwrap()
    let position = restored.index([1, 0]) // 0-based coordinates; result is 1
    let value = restored.value(position)
    let numpy_bytes = @mat.write_npy(restored)

    array.reshape([4, 1]) 保持列优先线性顺序;array.permute_axes([1, 0]) 转置二维数组,也支持更高维置换。file.select(["signal"]) 按请求顺序提取变量。NPY 输入使用 read_npy(bytes, "signal");标量转为 [1,1]、一维向量转为 [n,1],二维及以上形状保持。

    Value 区分 Signed(Int64)、Unsigned(UInt64)、Floating(Double)、Boolean(Bool)。64 位整数不会经由浮点数传递。raw_array 接受规范的小端列优先字节,适合批量桥接及保留 NaN 的内部编码。公开数组字段可被调用方构造,写入时会重新校验形状与载荷。

    混合密集/稀疏文件使用 read_document / write_document;read_mat 保留旧的密集 API,并对稀疏变量明确报错。document.get(name) 返回 Dense(NumericArray) 或 Sparse(SparseArray)。write_document(variables, compressed=true) 启用压缩,compare_documents(left, right) 返回按名称匹配的精确差异。参见 科研工作流。

    #Python 与 MATLAB 示例

    MoonMatBridge 写入的 MAT 可由 SciPy 读取;NPY 可以直接由 NumPy 读取:

    import numpy as np from scipy.io import loadmat, savemat data = loadmat("sample.mat") assert int(data["sample_id"][0, 0]) == 9007199254740993 temperature = np.load("temperature.npy", allow_pickle=False) assert temperature.shape == (2, 3) # 压缩和未压缩的 dense numeric MAT 都可读入 MoonMatBridge。 savemat("python.mat", {"signal": np.arange(12).reshape(3, 4)}, do_compression=True)

    仓库提供 SciPy 示例 和 MATLAB 示例。MATLAB 示例是供用户运行的脚本,当前没有实际 MATLAB/Octave 执行结果;兼容性证据来自独立 SciPy/NumPy。

    #构建与验证

    使用已安装的 MoonBit、Node.js 22+,native 目标还需要 C 编译器。开发验证另外需要 Python 3.12+:

    python -m venv .venv .\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt npm run check npm test npm run build npm run build:native npm run verify npm run package npm run verify:registry

    开发脚本优先使用 MOON_HOME / MOONMAT_MOON,也能读取忽略提交的 .local-toolchain.json,字段为 moonHome、gcc。Windows C 编译器可以通过 MOONMAT_GCC 指定;独立验证 Python 可以通过 MOONMAT_PYTHON 指定。不会修改系统 PATH、用户配置或已有项目。

    npm run verify:registry 创建独立项目,使用固定版本的 moon add 下载依赖;禁止本地 workspace/path 替代,核对已下载源码,并在 JS、wasm-gc、native 上验证六个完整消费者场景。示例位于 examples/registry_consumer。发布时使用 .moonignore 的明确文件范围,并通过 moon package --list 核对;开发工具、构建输出、个人报名材料及验证工作目录不进入 Mooncakes 包。

    本地验证使用 MoonBit 0.1.20260920 (914d7da)、Node v24.13.0、GCC 16.2.0、Python 3.12.5、SciPy 1.15.3、NumPy 2.2.6。scripts/verify.mjs 执行三目标测试、直接示例、构建、压缩差分测试和真实文件互通,并记录源文件指纹。

    • 59 项 MoonBit 测试,各在 JS / wasm-gc / native 执行一次。
    • 62 项独立 SciPy/NumPy 验证分组:21 个密集科研数组、两宿主各 72 个 NPY 导入文件,以及递归混合类型、六种字符存储标签、稀疏、压缩写入、转换流程、快照、精确差异和失败原子性。
    • 704 个 zlib 解压对照流、2,072 个截断输入检查,以及 44 个 MoonBit 压缩输出的独立解码检查。

    报告位于 verification/reports。这些报告是本地构建与互通证据。GitHub Actions 另外执行完整 Linux 科研互通验证并保存报告。各版本公开下载核对以对应发布报告为准;赛事提交、主办方验收及获奖仍需独立确认。报名所需个人材料及本人申报书见 报名清单。

    #许可与后续

    Apache-2.0,详见 LICENSE、NOTICE、第三方与参考来源。实现由 AI 辅助完成;关键格式逻辑可在 MoonBit 源码中直接审查,使用独立实现做验证。

    后续优先评估结构化科研数据与扫描/流式接口。当前无损快照保存数组内容和存储元数据,不承诺恢复原始 MAT 头部或压缩字节;精确差异不提供浮点容差比较。各版本的实现范围与验证证据见 CHANGELOG。

    MatError

    pub(all) suberror MatError {
    MatError(String, Int, String)
    } derive(Eq,
    Debug
    )

    Error offsets refer to the current MAT stream, or the expanded stream for compressed data.

    MatError::code

    fn MatError::code(self : MatError) -> String

    MatError::equal

    fn MatError::equal(MatError, MatError) -> Bool

    MatError::message

    fn MatError::message(self : MatError) -> String

    MatError::not_equal

    fn MatError::not_equal(x : MatError, y : MatError) -> Bool

    MatError::offset

    fn MatError::offset(self : MatError) -> Int

    MatError::to_repr

    CellArray

    pub(all) struct CellArray {
    name : String
    shape : Array[Int]
    values : Array[MatNode]
    is_global : Bool
    } derive(
    Debug
    )

    Children are in column-major order. Nested matrices may have an empty name.

    CharArray

    pub(all) struct CharArray {
    name : String
    shape : Array[Int]
    encoding : CharEncoding
    data : Bytes
    is_global : Bool
    } derive(
    Debug
    )

    CharEncoding

    pub(all) enum CharEncoding {
    Int8Text
    UInt8Text
    UInt16Text
    Utf8
    Utf16
    Utf32
    } derive(Eq,
    Debug
    )

    Character payloads retain their storage encoding; multi-byte units are canonical little-endian.

    CharEncoding::equal

    CharEncoding::name

    fn CharEncoding::name(self : CharEncoding) -> String

    CharEncoding::not_equal

    fn CharEncoding::not_equal(x : CharEncoding, y : CharEncoding) -> Bool

    DType

    pub(all) enum DType {
    Float64
    Float32
    Int8
    UInt8
    Int16
    UInt16
    Int32
    UInt32
    Int64
    UInt64
    Logical
    } derive(Eq,
    Debug
    )

    Supported dense array classes. All payloads use little-endian, column-major order.

    DType::equal

    fn DType::equal(DType, DType) -> Bool

    DType::name

    fn DType::name(self : DType) -> String

    DType::not_equal

    fn DType::not_equal(x : DType, y : DType) -> Bool

    DType::to_repr

    DType::width

    fn DType::width(self : DType) -> Int

    DifferenceSample

    pub(all) struct DifferenceSample {
    plane : String
    index : Int
    coordinates : Array[Int]
    before : Bytes
    after : Bytes
    } derive(
    Debug
    )

    DocumentDifference

    pub(all) struct DocumentDifference {
    content_equal : Bool
    variable_order_changed : Bool
    changed_variables : Int
    variables : Array[VariableDifference]
    } derive(
    Debug
    )

    Limits

    pub(all) struct Limits {
    max_file_bytes : Int
    max_expanded_bytes : Int
    max_elements : Int
    max_variables : Int
    max_dimensions : Int
    max_name_bytes : Int
    } derive(Eq,
    Debug
    )

    Limits are validated before reading or allocating according to file-controlled lengths.

    Limits::equal

    fn Limits::equal(Limits, Limits) -> Bool

    Limits::not_equal

    fn Limits::not_equal(x : Limits, y : Limits) -> Bool

    Limits::to_repr

    MatDocument

    pub(all) struct MatDocument {
    description : String
    little_endian : Bool
    variables : Array[MatVariable]
    } derive(
    Debug
    )

    MatDocument::convert_storage

    fn MatDocument::convert_storage(self : MatDocument, name : String, sparse : Bool, limits? : Limits) -> Array[MatVariable] raise MatError

    Replace one named variable with explicit dense/CSC storage. Other variables remain intact.

    MatDocument::get

    fn MatDocument::get(self : MatDocument, name : String) -> MatVariable?

    MatDocument::select

    fn MatDocument::select(self : MatDocument, names : Array[String]) -> Array[MatVariable] raise MatError

    MatFile

    pub(all) struct MatFile {
    description : String
    little_endian : Bool
    arrays : Array[NumericArray]
    } derive(
    Debug
    )

    Original file byte order is reported; arrays are normalized to little-endian.

    MatFile::get

    fn MatFile::get(self : MatFile, name : String) -> NumericArray?

    MatFile::select

    fn MatFile::select(self : MatFile, names : Array[String], limits? : Limits) -> Array[NumericArray] raise MatError

    Select variables in requested order, rejecting missing or ambiguous names.

    MatFile::to_repr

    MatNode

    pub(all) enum MatNode {
    Numeric(NumericArray)
    Csc(SparseArray)
    Character(CharArray)
    Cell(CellArray)
    Structure(StructArray)
    } derive(
    Debug
    )

    MatNode::name

    fn MatNode::name(self : MatNode) -> String

    MatNode::shape

    fn MatNode::shape(self : MatNode) -> Array[Int]

    MatNode::to_repr

    MatRootInfo

    pub(all) struct MatRootInfo {
    name : String
    class_id : Int
    shape : Array[Int]
    is_global : Bool
    is_complex : Bool
    is_logical : Bool
    compressed : Bool
    } derive(
    Debug
    )

    Validated root metadata; offsets are intentionally not exposed or cached.

    MatTree

    pub(all) struct MatTree {
    description : String
    little_endian : Bool
    variables : Array[MatNode]
    } derive(
    Debug
    )

    MatTree::get

    fn MatTree::get(self : MatTree, name : String) -> MatNode?

    MatTree::select

    fn MatTree::select(self : MatTree, names : Array[String]) -> Array[MatNode] raise MatError

    MatTree::to_repr

    MatVariable

    pub(all) enum MatVariable {
    Dense(NumericArray)
    Sparse(SparseArray)
    } derive(
    Debug
    )

    MatVariable::name

    fn MatVariable::name(self : MatVariable) -> String

    MatVariable::stored_elements

    fn MatVariable::stored_elements(self : MatVariable) -> Int

    NumericArray

    pub(all) struct NumericArray {
    name : String
    dtype : DType
    shape : Array[Int]
    real : Bytes
    imag : Bytes?
    is_global : Bool
    } derive(
    Debug
    )

    Arrays own their canonical payload. Writers revalidate public fields before serialization.

    NumericArray::gather_axis

    fn NumericArray::gather_axis(self : NumericArray, axis : Int, indices : Array[Int], limits? : Limits) -> NumericArray raise MatError

    Gather one axis in caller-specified order, including repeated indices, without numeric conversion.

    NumericArray::index

    fn NumericArray::index(self : NumericArray, coordinates : Array[Int]) -> Int raise MatError

    Convert multidimensional zero-based coordinates to a column-major linear index.

    NumericArray::is_complex

    fn NumericArray::is_complex(self : NumericArray) -> Bool

    NumericArray::length

    fn NumericArray::length(self : NumericArray) -> Int

    NumericArray::permute_axes

    fn NumericArray::permute_axes(self : NumericArray, axes : Array[Int], limits? : Limits) -> NumericArray raise MatError

    axes[k] identifies the source axis used for output axis k. Both planes retain raw bits.

    NumericArray::reshape

    fn NumericArray::reshape(self : NumericArray, shape : Array[Int], limits? : Limits) -> NumericArray raise MatError

    Reshape in column-major order without converting or copying immutable payload bytes.

    NumericArray::slice

    fn NumericArray::slice(self : NumericArray, starts : Array[Int], counts : Array[Int], steps? : Array[Int], limits? : Limits) -> NumericArray raise MatError

    Zero-based strided slicing. Counts are output dimensions; positive steps retain raw bits.

    NumericArray::to_sparse

    fn NumericArray::to_sparse(self : NumericArray, limits? : Limits) -> SparseArray raise MatError

    Only all-zero byte patterns are omitted. Signed zero, NaN payloads and complex data survive.

    NumericArray::value

    fn NumericArray::value(self : NumericArray, index : Int, imaginary? : Bool) -> Value raise MatError

    SparseArray

    pub(all) struct SparseArray {
    name : String
    dtype : DType
    shape : Array[Int]
    row_indices : Array[Int]
    col_ptrs : Array[Int]
    real : Bytes
    imag : Bytes?
    nzmax : Int
    is_global : Bool
    } derive(
    Debug
    )

    Canonical CSC sparse double/logical matrix. Payload includes all stored slots, including unused capacity.

    SparseArray::nnz

    fn SparseArray::nnz(self : SparseArray) -> Int

    Number of used CSC entries, including explicit zeros; differs from allocated capacity.

    SparseArray::to_dense

    fn SparseArray::to_dense(self : SparseArray, limits? : Limits) -> NumericArray raise MatError

    Explicit densification is bounded by shape product; huge sparse shapes never expand implicitly.

    StructArray

    pub(all) struct StructArray {
    name : String
    shape : Array[Int]
    fields : Array[String]
    values : Array[MatNode]
    class_name : String?
    is_global : Bool
    } derive(
    Debug
    )

    Values are element-major, then field order: values[element * fields.length() + field]. Some(class_name) represents the documented legacy mxOBJECT class, as data only.

    TreeLimits

    pub(all) struct TreeLimits {
    max_depth : Int
    max_nodes : Int
    max_fields : Int
    } derive(Eq,
    Debug
    )

    TreeLimits::equal

    fn TreeLimits::equal(TreeLimits, TreeLimits) -> Bool

    TreeLimits::not_equal

    fn TreeLimits::not_equal(x : TreeLimits, y : TreeLimits) -> Bool

    Value

    pub(all) enum Value {
    Signed(Int64)
    Unsigned(UInt64)
    Floating(Double)
    Boolean(Bool)
    } derive(
    Debug
    )

    Exact scalar representation; integer values never pass through Double.

    Value::to_repr

    VariableDifference

    pub(all) struct VariableDifference {
    name : String
    status : String
    metadata : Array[String]
    real_differences : Int
    imag_differences : Int
    samples : Array[DifferenceSample]
    truncated : Bool
    } derive(
    Debug
    )

    compare_documents

    fn compare_documents(left : MatDocument, right : MatDocument, max_samples? : Int, limits? : Limits) -> DocumentDifference raise MatError

    Match by variable name, compare canonical bits and metadata, and ignore original header/compression/endian. Sample budget is global across the report. All comparable slots are still counted, including unused CSC capacity.

    concat_arrays

    fn concat_arrays(name : String, arrays : Array[NumericArray], axis : Int, limits? : Limits) -> NumericArray raise MatError

    Concatenate compatible arrays along one axis. Every plane is copied as canonical raw bytes.

    default_limits

    fn default_limits() -> Limits

    default_tree_limits

    fn default_tree_limits() -> TreeLimits

    deflate_zlib

    fn deflate_zlib(bytes : Bytes, max_bytes? : Int) -> Bytes raise MatError

    Deterministic bounded zlib writer: greedy LZ77 with fixed Huffman codes, or stored blocks when smaller. Input is bounded to 64 MiB; no external compressor, dictionaries, timestamps or platform variation.

    dtype_from_name

    fn dtype_from_name(name : String) -> DType raise MatError

    inflate_zlib

    fn inflate_zlib(bytes : Bytes, max_bytes? : Int) -> Bytes raise MatError

    Decode a single complete zlib stream. Verifies header, block lengths, stream end and Adler-32.

    inspect_roots

    fn inspect_roots(bytes : Bytes, limits? : Limits, tree_limits? : TreeLimits) -> Array[MatRootInfo] raise MatError

    Full validation with no persistent data trees; compressed roots are decoded.

    numeric_array

    fn numeric_array(name : String, dtype : DType, shape : Array[Int], values : Array[Value], imaginary? : Array[Value], is_global? : Bool, limits? : Limits) -> NumericArray raise MatError

    Build an array from exact scalar values in column-major order. Float32 conversion rounds to IEEE binary32.

    raw_array

    fn raw_array(name : String, dtype : DType, shape : Array[Int], real : Bytes, imag? : Bytes, is_global? : Bool, limits? : Limits) -> NumericArray raise MatError

    Build an array from canonical little-endian raw payload; preserves NaN payload bits and signed zero.

    raw_sparse_array

    fn raw_sparse_array(name : String, dtype : DType, shape : Array[Int], row_indices : Array[Int], col_ptrs : Array[Int], real : Bytes, imag? : Bytes, nzmax? : Int, is_global? : Bool, limits? : Limits) -> SparseArray raise MatError

    read_document

    fn read_document(bytes : Bytes, limits? : Limits) -> MatDocument raise MatError

    Read dense and CSC sparse MAT Level 5. Unknown classes fail; nothing is silently skipped.

    read_mat

    fn read_mat(bytes : Bytes, limits? : Limits) -> MatFile raise MatError

    Compatibility API for dense-only consumers. Sparse variables fail explicitly; use read_document for mixed files.

    read_npy

    fn read_npy(bytes : Bytes, name : String, limits? : Limits) -> NumericArray raise MatError

    Read primitive numeric NPY v1/v2/v3, normalize endian and C/Fortran order. Scalar and vector NPY shapes become [1,1] and [n,1] for MAT interoperability. No Python expressions or pickle/object payloads are evaluated.

    read_selected

    fn read_selected(bytes : Bytes, names : Array[String], limits? : Limits, tree_limits? : TreeLimits) -> MatTree raise MatError

    Validate every variable while constructing only the requested data trees.

    read_tree

    fn read_tree(bytes : Bytes, limits? : Limits, tree_limits? : TreeLimits) -> MatTree raise MatError

    utf8_char_array

    fn utf8_char_array(name : String, shape : Array[Int], text : String, is_global? : Bool, limits? : Limits) -> CharArray raise MatError

    UTF-8 dimensions count Unicode scalars, following SciPy's UTF-8 MAT representation.

    validate_document

    fn validate_document(arrays : Array[MatVariable], limits? : Limits) -> Unit raise MatError

    Validate public variable fields, duplicate names and aggregate resource limits without output allocation.

    version

    fn version() -> String

    Version of this source build; tagged releases retain their own value.

    write_document

    fn write_document(arrays : Array[MatVariable], compressed? : Bool, limits? : Limits) -> Bytes raise MatError

    Write deterministic little-endian dense/CSC MAT Level 5, optionally compressed.

    write_mat

    fn write_mat(arrays : Array[NumericArray], compressed? : Bool, limits? : Limits) -> Bytes raise MatError

    Backwards-compatible dense writer; write_document handles mixed dense/CSC data.

    write_npy

    fn write_npy(array : NumericArray, limits? : Limits) -> Bytes raise MatError

    Export one dense array as NPY v1.0 with fortran_order=True. Complex values are interleaved.

    write_tree

    fn write_tree(variables : Array[MatNode], compressed? : Bool, limits? : Limits, tree_limits? : TreeLimits) -> Bytes raise MatError

    Preflight all nodes, then write directly to a privately owned fixed buffer.