sparse-ir-capi 0.8.0

C API for SparseIR Rust implementation
Documentation

SparseIR C-API

Crates.io Documentation License: MIT OR Apache-2.0

This crate provides a C API for the SparseIR library.

Language Support

  • Fortran (via ISO_C_BINDING)
  • Julia (via ccall)
  • Python (via ctypes)
  • C/C++
  • Other languages that can call C ABIs

Features

Currently Implemented

See the header file for the complete API: include/sparseir/sparseir.h

Sampling: Supported Type Patterns

The C-API provides eval (coefficients → values) and fit (values → coefficients) functions with different type combinations. The suffix indicates input/output types:

  • d = double (f64, real)
  • z = double complex (Complex64)

Evaluate Functions (Coefficients → Values)

Function Tau Matsubara (full) Matsubara (positive_only)
spir_sampling_eval_dd
spir_sampling_eval_dz
spir_sampling_eval_zz ✅*

Fit Functions (Values → Coefficients)

Function Tau Matsubara (full) Matsubara (positive_only)
spir_sampling_fit_dd
spir_sampling_fit_zd ✅*
spir_sampling_fit_zz ✅**

* For Matsubara (full), fit_zd internally fits complex coefficients and returns their real parts. This is physically correct for Green's functions where IR coefficients are guaranteed to be real by symmetry.

** For Matsubara (positive_only), fit_zz internally fits to real coefficients and converts to complex with zero imaginary parts. This is valid because IR coefficients are guaranteed to be real for physical Green's functions.

* For Matsubara (positive_only), eval_zz extracts real parts from input coefficients and evaluates. This is valid because IR coefficients are guaranteed to be real for physical Green's functions.

Notes

  • Tau sampling: Uses real transformation matrix. Supports dd for real data, zz for complex data (real/imag parts transformed independently).
  • Matsubara (full): Uses complex transformation matrix with both positive and negative frequencies. Natural type is zz. The dz evaluate is supported for real coefficients (physically guaranteed for Green's functions).
  • Matsubara (positive_only): Uses only positive frequencies with complex matrix but real coefficients. Natural types are dz (evaluate) and zd (fit). Also supports zz variants by extracting/adding zero imaginary parts.

Error Handling

All C-API functions use catch_unwind() to prevent panics from crossing the FFI boundary:

  • Returns error codes instead of panicking
  • Process remains stable even on internal errors
  • Safe for production use

Building

# Build shared library (.dylib on macOS, .so on Linux, .dll on Windows)
# The C header is automatically generated by cbindgen during build
cargo build --release

# Run tests
cargo test

Installation

Install the header and shared library to your system:

# Install cargo-c (first time only)
cargo install cargo-c

# Install header and shared library to system directories
cargo cinstall --release

# Or install to a custom prefix
cargo cinstall --release --prefix /custom/path

By default, cargo cinstall installs to:

  • Header: /usr/local/include/sparse_ir_capi/sparse_ir_capi.h (Linux/macOS)
  • Library: /usr/local/lib/libsparse_ir_capi.so (Linux) or .dylib (macOS)
  • Static library: /usr/local/lib/libsparse_ir_capi.a
  • pkg-config: /usr/local/lib/pkgconfig/sparse_ir_capi.pc

After installation, you can use pkg-config to find the library:

pkg-config --cflags --libs sparse-ir-capi

Note on Header Files:

The header file include/sparseir/sparseir.h is automatically generated by cbindgen during cargo build with C++ compatibility enabled (--cpp-compat flag). The header is used directly without post-processing.

The Cargo.toml is configured with generation = false so that cargo cinstall uses the header from assets/sparse_ir_capi.h. This file is a copy of include/sparseir/sparseir.h and is maintained in the repository (not generated by build.rs to avoid cargo publish issues).

Do not manually edit include/sparseir/sparseir.h - it is automatically generated and will be overwritten on the next build. When the header changes, update assets/sparse_ir_capi.h manually or via CI/CD.

Header Generation

The C header (include/sparseir/sparseir.h) is automatically generated from Rust source code using cbindgen:

  • Build time: Header is regenerated automatically when Rust sources change
  • Manual regeneration: cargo build (header is created by build.rs)
  • Configuration: See cbindgen.toml for generation settings

Do not edit the generated header manually - edit the Rust source code instead!

Usage Examples

Julia

# Load library
const lib = "../target/release/libsparse_ir_capi.dylib"

# Create kernel
kernel_ptr = Ref{Ptr{Cvoid}}()
status = ccall((:spir_logistic_kernel_new, lib),
               Int32, (Float64, Ref{Ptr{Cvoid}}),
               10.0, kernel_ptr)

# Compute kernel value
result = Ref{Float64}()
status = ccall((:spir_kernel_compute, lib),
               Int32, (Ptr{Cvoid}, Float64, Float64, Ref{Float64}),
               kernel_ptr[], 0.5, 0.5, result)

println("K(0.5, 0.5) = ", result[])

# Release
ccall((:spir_kernel_release, lib), Cvoid, (Ptr{Cvoid},), kernel_ptr[])

See examples/test_julia.jl for a complete example.

C

#include "sparseir/sparseir.h"
#include <stdio.h>

int main() {
    // libsparseir compatible API
    int status;
    spir_kernel* kernel = spir_logistic_kernel_new(10.0, &status);

    if (kernel == NULL || status != SPIR_COMPUTATION_SUCCESS) {
        fprintf(stderr, "Failed to create kernel: status = %d\n", status);
        return 1;
    }

    double result;
    status = spir_kernel_compute(kernel, 0.5, 0.5, &result);
    printf("K(0.5, 0.5) = %f\n", result);

    spir_kernel_release(kernel);
    return 0;
}

Testing

Run the Julia example:

cd examples
julia test_julia.jl

Memory Management

All objects returned by *_new() functions must be released with their corresponding *_release() function:

  • spir_kernel_release()
  • (more to come: spir_basis_release(), etc.)

All objects are immutable and thread-safe.

License

This crate is dual-licensed under the terms of the MIT license and the Apache License (Version 2.0).