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)
}