Rust bindings for selected header-only kernels from
MCPNet (and its splash dependency),
exposed through cxx.
The bindings cover the kernels needed to build a typical MCPNet pipeline end-to-end (rank → cumulative histogram → adaptive MI, or BSpline weights → BSpline MI, or z-score → Pearson) plus the post-processing transforms and filters used to combine, normalize, and prune a correlation matrix.
Every kernel that has a floating-point output type is exposed in both
f32 and f64 flavors (*_f32 / *_f64).
The C++ sources are header-only; build.rs compiles a small shim
(src/mcpnet.cpp) using cxx-build and pulls in
MCPNet, splash, and a vendored header-only fmt directly from the
src/mcpnet git submodule.
git submodule update --init --recursive
cargo build
cargo testNo MPI, OpenMP, or HDF5 are required.
| Function | Wraps | Returns |
|---|---|---|
adaptive_mi_kernel_{f32,f64}(x_ranks: &[usize], y_ranks: &[usize]) |
mcp::kernel::AdaptivePartitionRankMIKernel2 |
MI of two rank vectors (bits) |
pearson_kernel_{f32,f64}(first, second) |
mcp::correlation::PearsonKernel |
Pearson r (inputs must be z-scored) |
bspline_mi_kernel_{f32,f64}(first, second, num_bins, num_samples) |
mcp::kernel::BSplineMIKernel |
H(X) + H(Y) − H(X,Y) from BSpline weight vectors |
| Function | Wraps | Notes |
|---|---|---|
rank_{f32,f64}(in, out) |
splash::kernel::Rank<IT, usize, 0, false> |
Descending, first rank = 0 |
integral_cumulative_histogram(in, out) |
mcp::kernel::IntegralCumulativeHistogramKernel |
out.len() ≥ in.len() + 1 |
bspline_weights_{f32,f64}(in, num_bins, spline_order, num_samples, out) |
mcp::kernel::BSplineWeightsKernel |
Output is num_bins·num_samples + 1; last slot holds 1D entropy |
standard_score_{f32,f64}(in, out) |
splash::kernel::StandardScore<T, T, false> |
Population variance, matches MCPNet's pearson.cpp |
All take two slices and a same-typed output slice (scale_kernel is unary).
| Function | Computes |
|---|---|
add_kernel_{f32,f64}(a, b, out) |
out = a + b |
sub_kernel_{f32,f64} |
out = a − b |
multiply_kernel_{f32,f64} |
out = a · b |
ratio_kernel_{f32,f64} |
out = a / b (NaN/Inf-safe) |
max_kernel_{f32,f64} |
out = max(a, b) |
min_kernel_{f32,f64} |
out = min(a, b) |
madd_kernel_{f32,f64}(a, b, coeff, out) |
out = a + coeff · b |
weighted_mean_kernel_{f32,f64}(a, b, alpha, beta, out) |
out = α·a + β·b |
scale_kernel_{f32,f64}(in, coeff, out) |
out = coeff · in |
Auxiliary (mean, stdev) pairs are passed as separate scalars or parallel
arrays.
| Function | Computes |
|---|---|
stouffer_kernel_{f32,f64}(value, m1, s1, m2, s2) |
(z₁ + z₂)/√2 |
stouffer_vector_kernel_{f32,f64}(in, m1, s1, m2_means, m2_stds, out) |
Stouffer combine, vector form |
zscored_stouffer_kernel_{f32,f64}(zi, zj, out) |
out[k] = (zi[k] + zj[k])/√2 |
weighted_stouffer_kernel_{f32,f64}(value, m1, s1, m2, s2) |
Variance-weighted Stouffer |
| Function | Computes |
|---|---|
clr_kernel_{f32,f64}(value, m1, s1, m2, s2) |
√(z₁² + z₂²) |
clr_vector_kernel_{f32,f64}(in, m1, s1, m2_means, m2_stds, out) |
CLR vector form |
zscored_clr_kernel_{f32,f64}(zi, zj, out) |
out[k] = √(zi[k]² + zj[k]²) |
| Function | Computes |
|---|---|
threshold_kernel_{f32,f64}(in, min, max, default_val, out) |
Keep min ≤ in[i] ≤ max; otherwise default_val |
inverted_threshold_kernel_{f32,f64} |
Keep in[i] ≤ min or in[i] ≥ max; otherwise default_val |
threshold2_kernel_{f32,f64}(in, aux, min, max, default_val, out) |
Predicate driven by aux |
inverted_threshold2_kernel_{f32,f64} |
Inverted predicate driven by aux |
mask_kernel_{f32,f64}(in, mask: &[u8], negate, default_val, out) |
Keep where mask[i] != 0 (xor negate) |
These all operate on a pair of MI rows row_x, row_z and the index pair
(x, z). Pass an empty tfs slice to disable the optional TF mask.
| Function | Computes |
|---|---|
dpi_kernel_{f32,f64}(x, z, row_x, row_z, tolerance) -> bool |
true if edge (x, z) should be deleted by DPI |
dpi_tf_kernel_{f32,f64}(x, z, row_x, row_z, tfs, tolerance) -> bool |
DPI variant with a TF mask (tfs[i] > 0 ⇒ TF) |
mcp2_maxmin_kernel_{f32,f64}(x, z, row_x, row_z, tfs) |
maxᵧ min(row_x[y], row_z[y]) |
mcp_ratio_kernel_{f32,f64}(x, z, row_x, row_z, tfs) |
row_x[z] / maxᵧ min(...) |
mcp_tolerance_kernel_{f32,f64}(x, z, row_x, row_z, tfs, clamped) |
1 − ratio; the minimum tolerance below which the edge is deleted |
mcp_diff_kernel_{f32,f64}(x, z, row_x, row_z, tfs) |
row_x[z] − maxᵧ min(...) |
- All inputs are validated on both the Rust and the C++ side
(
assert!/assert). Lengths must satisfy the per-kernel preconditions documented above. standard_score_*uses population variance (SampleStats = false) to match the convention used bymcp::correlation::PearsonKernel.mcp::kernel::Entropy1DKernelis referenced in commented-out code in MCPNet but is not defined; no wrapper is provided. The 1D BSpline entropy is available as the last element of the buffer produced bybspline_weights_*.mcp_diff_kernel_*is implemented manually becausemcp::kernel::mcp_diff_kernel<float, float>does not compile in upstream MCPNet (std::max(0.0, float)ambiguity). Behavior matches the upstream kernel for floating-point output types (theclampedbranch is dead code there).
build.rs— compilessrc/mcpnet.cppviacxx-buildinclude/mcpnet.h— declarations seen by the bridgesrc/mcpnet.cpp— thin C++ shims around the templated MCPNet/splash kernelssrc/lib.rs—#[cxx::bridge]module plus the public Rust API and unit testssrc/mcpnet/— MCPNet git submodule (providessplash,fmt, andCLI11transitively)
The Rust shim in this repository is provided as-is. The vendored MCPNet,
splash, fmt, and CLI11 sources retain their original licenses (see
src/mcpnet/LICENSE and the respective subprojects).