elli-gf2 0.1.0

Machine-first GF(2) elimination library with exact multi-backend reduction and auto-selection.
Documentation
use std::ffi::{CStr, c_char};

use crate::{
    Strategy, generate_banded, generate_er_sparse, generate_ldpc_like,
    io::load_sparse_columns_file, recommended_strategy, reduce_with_strategy,
};

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct ElliGf2Result {
    pub rank: u64,
    pub strategy: u32,
    pub ok: i32,
}

fn strategy_code(s: Strategy) -> u32 {
    match s {
        Strategy::SparseList => 0,
        Strategy::PackedCached => 1,
        Strategy::DenseMacro => 2,
        Strategy::Auto => 3,
    }
}

fn make_result(rows: u64, cols: Vec<Vec<u32>>) -> ElliGf2Result {
    let rows_usize = match usize::try_from(rows) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    let picked = recommended_strategy(&cols);
    let out = reduce_with_strategy(rows_usize, &cols, Strategy::Auto);

    ElliGf2Result {
        rank: out.rank as u64,
        strategy: strategy_code(picked),
        ok: 1,
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn elli_gf2_strategy_name(strategy: u32) -> *const c_char {
    match strategy {
        0 => c"SparseList".as_ptr(),
        1 => c"PackedCached".as_ptr(),
        2 => c"DenseMacro".as_ptr(),
        3 => c"Auto".as_ptr(),
        _ => c"Unknown".as_ptr(),
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn elli_gf2_reduce_er_auto(
    rows: u64,
    cols: u64,
    density: f64,
    seed: u64,
) -> ElliGf2Result {
    let rows_usize = match usize::try_from(rows) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let cols_usize = match usize::try_from(cols) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    let generated = generate_er_sparse(rows_usize, cols_usize, density, seed);
    make_result(rows, generated)
}

#[unsafe(no_mangle)]
pub extern "C" fn elli_gf2_reduce_ldpc_auto(
    rows: u64,
    cols: u64,
    col_weight: u64,
    seed: u64,
) -> ElliGf2Result {
    let rows_usize = match usize::try_from(rows) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let cols_usize = match usize::try_from(cols) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let weight_usize = match usize::try_from(col_weight) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    let generated = generate_ldpc_like(rows_usize, cols_usize, weight_usize, seed);
    make_result(rows, generated)
}

#[unsafe(no_mangle)]
pub extern "C" fn elli_gf2_reduce_banded_auto(
    rows: u64,
    cols: u64,
    bandwidth: u64,
    weight: u64,
    seed: u64,
) -> ElliGf2Result {
    let rows_usize = match usize::try_from(rows) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let cols_usize = match usize::try_from(cols) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let bandwidth_usize = match usize::try_from(bandwidth) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };
    let weight_usize = match usize::try_from(weight) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    let generated = generate_banded(rows_usize, cols_usize, bandwidth_usize, weight_usize, seed);
    make_result(rows, generated)
}

#[unsafe(no_mangle)]
pub extern "C" fn elli_gf2_reduce_file_auto(path: *const c_char) -> ElliGf2Result {
    if path.is_null() {
        return ElliGf2Result {
            rank: 0,
            strategy: 3,
            ok: 0,
        };
    }

    let c_path = unsafe { CStr::from_ptr(path) };
    let path_str = match c_path.to_str() {
        Ok(s) => s,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    let loaded = match load_sparse_columns_file(path_str) {
        Ok(v) => v,
        Err(_) => {
            return ElliGf2Result {
                rank: 0,
                strategy: 3,
                ok: 0,
            };
        }
    };

    make_result(loaded.rows as u64, loaded.cols)
}