r_mathlib 0.2.0

A port of R's `nmath` stats module to Rust.
Documentation
use std::{env, ffi::OsString, fs, path::PathBuf};

const FN_NAMES: &[&str] = &[
    "R_pow",
    "R_pow_di",
    "norm_rand",
    "unif_rand",
    "R_unif_index",
    "exp_rand",
    "set_seed",
    "get_seed",
    "dnorm4",
    "pnorm5",
    "qnorm5",
    "rnorm",
    "pnorm_both",
    "dunif",
    "punif",
    "qunif",
    "runif",
    "dgamma",
    "pgamma",
    "qgamma",
    "rgamma",
    "log1pmx",
    "log1pexp",
    "log1mexp",
    "lgamma1p",
    "logspace_add",
    "logspace_sub",
    "logspace_sum",
    "dbeta",
    "pbeta",
    "qbeta",
    "rbeta",
    "dlnorm",
    "plnorm",
    "qlnorm",
    "rlnorm",
    "dchisq",
    "pchisq",
    "qchisq",
    "rchisq",
    "dnchisq",
    "pnchisq",
    "qnchisq",
    "rnchisq",
    "df",
    "pf",
    "qf",
    "rf",
    "dt",
    "pt",
    "qt",
    "rt",
    "dbinom_raw",
    "dbinom",
    "pbinom",
    "qbinom",
    "rbinom",
    "rmultinom",
    "dcauchy",
    "pcauchy",
    "qcauchy",
    "rcauchy",
    "dexp",
    "pexp",
    "qexp",
    "rexp",
    "dgeom",
    "pgeom",
    "qgeom",
    "rgeom",
    "dhyper",
    "phyper",
    "qhyper",
    "rhyper",
    "dnbinom",
    "pnbinom",
    "qnbinom",
    "rnbinom",
    "dnbinom",
    "pnbinom",
    "qnbinom",
    "rnbinom",
    "dnbinom_mu",
    "pnbinom_mu",
    "qnbinom_mu",
    "rnbinom_mu",
    "dpois_raw",
    "dpois",
    "ppois",
    "qpois",
    "rpois",
    "dweibull",
    "pweibull",
    "qweibull",
    "rweibull",
    "dlogis",
    "plogis",
    "qlogis",
    "rlogis",
    "dnbeta",
    "pnbeta",
    "qnbeta",
    "rnbeta",
    "dnf",
    "pnf",
    "qnf",
    "dnt",
    "pnt",
    "qnt",
    "ptukey",
    "qtukey",
    "dwilcox",
    "pwilcox",
    "qwilcox",
    "rwilcox",
    "dsignrank",
    "psignrank",
    "qsignrank",
    "rsignrank",
    "gammafn",
    "lgammafn",
    "lgammafn_sign",
    "dpsifn",
    "psigamma",
    "digamma",
    "trigamma",
    "tetragamma",
    "pentagamma",
    "beta",
    "lbeta",
    "choose",
    "lchoose",
    "bessel_i",
    "bessel_j",
    "bessel_k",
    "bessel_y",
    "bessel_i_ex",
    "bessel_j_ex",
    "bessel_k_ex",
    "bessel_y_ex",
    "imax2",
    "imin2",
    "fmax2",
    "fmin2",
    "sign",
    "fprec",
    "fround",
    "fsign",
    "ftrunc",
    "log1pmx",
    "lgamma1p",
    "cospi",
    "sinpi",
    "tanpi",
    "logspace_add",
    "logspace_sub",
];

fn main() {
    let c_test = OsString::from("c");
    cc::Build::new()
        .define("MATHLIB_STANDALONE", "1")
        .include("R/nmath")
        .include("R/include")
        .include("R/config")
        .files(
            fs::read_dir("R/nmath")
                .unwrap()
                .chain(fs::read_dir("R/nmath/standalone").unwrap())
                .filter_map(|entry| {
                    let path = entry.unwrap().path();
                    if path.extension() == Some(c_test.as_os_str()) {
                        Some(path)
                    } else {
                        None
                    }
                }),
        )
        .warnings(false)
        .compile("nmath");

    let mut builder = bindgen::Builder::default()
        .header("wrapper.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks));
    for fn_name in FN_NAMES.iter() {
        builder = builder.allowlist_function(fn_name);
    }
    let bindings = builder.generate().expect("Unable to generate bindings");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect(&format!("Cannot write to OUT_DIR {}", out_path.display()));
}