use pyo3::prelude::*;
use scirs2_core::python::numpy_compat::{scirs_to_numpy_array1, Array1};
use scirs2_numpy::{PyArray1, PyReadonlyArray1};
use scirs2_special::gamma::polygamma;
use scirs2_special::{bessel, erf as erf_mod, gamma as gamma_fn};
#[pyfunction]
fn gamma_py(x: f64) -> PyResult<f64> {
Ok(gamma_fn(x))
}
#[pyfunction]
fn lgamma_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::gamma::gammaln(x))
}
#[pyfunction]
fn digamma_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::gamma::digamma(x))
}
#[pyfunction]
fn beta_py(a: f64, b: f64) -> PyResult<f64> {
Ok(scirs2_special::gamma::beta(a, b))
}
#[pyfunction]
fn j0_py(x: f64) -> PyResult<f64> {
Ok(bessel::j0(x))
}
#[pyfunction]
fn j1_py(x: f64) -> PyResult<f64> {
Ok(bessel::j1(x))
}
#[pyfunction]
fn jn_py(n: i32, x: f64) -> PyResult<f64> {
Ok(bessel::jn(n, x))
}
#[pyfunction]
fn y0_py(x: f64) -> PyResult<f64> {
Ok(bessel::y0(x))
}
#[pyfunction]
fn y1_py(x: f64) -> PyResult<f64> {
Ok(bessel::y1(x))
}
#[pyfunction]
fn yn_py(n: i32, x: f64) -> PyResult<f64> {
Ok(bessel::yn(n, x))
}
#[pyfunction]
fn i0_py(x: f64) -> PyResult<f64> {
Ok(bessel::i0(x))
}
#[pyfunction]
fn i1_py(x: f64) -> PyResult<f64> {
Ok(bessel::i1(x))
}
#[pyfunction]
fn k0_py(x: f64) -> PyResult<f64> {
Ok(bessel::k0(x))
}
#[pyfunction]
fn k1_py(x: f64) -> PyResult<f64> {
Ok(bessel::k1(x))
}
#[pyfunction]
fn erf_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erf(x))
}
#[pyfunction]
fn erfc_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erfc(x))
}
#[pyfunction]
fn erfinv_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erfinv(x))
}
#[pyfunction]
fn erfcinv_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erfcinv(x))
}
#[pyfunction]
fn erfcx_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erfcx(x))
}
#[pyfunction]
fn erfi_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::erfi(x))
}
#[pyfunction]
fn dawsn_py(x: f64) -> PyResult<f64> {
Ok(erf_mod::dawsn(x))
}
#[pyfunction]
fn factorial_py(n: u32) -> PyResult<f64> {
scirs2_special::factorial(n)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn comb_py(n: u32, k: u32) -> PyResult<f64> {
scirs2_special::comb(n, k)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn perm_py(n: u32, k: u32) -> PyResult<f64> {
scirs2_special::perm(n, k)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn ellipk_py(m: f64) -> PyResult<f64> {
Ok(scirs2_special::elliptic_k(m))
}
#[pyfunction]
fn ellipe_py(m: f64) -> PyResult<f64> {
Ok(scirs2_special::elliptic_e(m))
}
#[pyfunction]
fn ellipkinc_py(phi: f64, m: f64) -> PyResult<f64> {
Ok(scirs2_special::elliptic_f(phi, m))
}
#[pyfunction]
fn ellipeinc_py(phi: f64, m: f64) -> PyResult<f64> {
Ok(scirs2_special::elliptic_e_inc(phi, m))
}
#[pyfunction]
fn polygamma_py(n: u32, x: f64) -> PyResult<f64> {
Ok(polygamma(n, x))
}
#[pyfunction]
fn zeta_py(s: f64) -> PyResult<f64> {
scirs2_special::zeta(s).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn hurwitz_zeta_py(s: f64, q: f64) -> PyResult<f64> {
scirs2_special::hurwitz_zeta(s, q)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn zetac_py(s: f64) -> PyResult<f64> {
scirs2_special::zetac(s).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn hyp0f1_py(v: f64, z: f64) -> PyResult<f64> {
scirs2_special::hyp0f1(v, z)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn hyp1f1_py(a: f64, b: f64, z: f64) -> PyResult<f64> {
scirs2_special::hyp1f1(a, b, z)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn hyp2f1_py(a: f64, b: f64, c: f64, z: f64) -> PyResult<f64> {
scirs2_special::hyp2f1(a, b, c, z)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn hyperu_py(a: f64, b: f64, x: f64) -> PyResult<f64> {
scirs2_special::hyperu(a, b, x)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn airy_ai_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::ai(x))
}
#[pyfunction]
fn airy_aip_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::aip(x))
}
#[pyfunction]
fn airy_bi_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::bi(x))
}
#[pyfunction]
fn airy_bip_py(x: f64) -> PyResult<f64> {
Ok(scirs2_special::bip(x))
}
#[pyfunction]
fn sici_si_py(x: f64) -> PyResult<f64> {
scirs2_special::si(x).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn sici_ci_py(x: f64) -> PyResult<f64> {
scirs2_special::ci(x).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn shichi_shi_py(x: f64) -> PyResult<f64> {
scirs2_special::shi(x).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn shichi_chi_py(x: f64) -> PyResult<f64> {
scirs2_special::chi(x).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn betainc_py(a: f64, b: f64, x: f64) -> PyResult<f64> {
scirs2_special::gamma::betainc_regularized(a, b, x)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn betaincinv_py(a: f64, b: f64, p: f64) -> PyResult<f64> {
scirs2_special::gamma::betaincinv(a, b, p)
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))
}
#[pyfunction]
fn gamma_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input.iter().map(|&v| gamma_fn(v)).collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn erf_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input.iter().map(|&v| erf_mod::erf(v)).collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn j0_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input.iter().map(|&v| bessel::j0(v)).collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn lgamma_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input
.iter()
.map(|&v| scirs2_special::gamma::gammaln(v))
.collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn erfc_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input.iter().map(|&v| erf_mod::erfc(v)).collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn digamma_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input
.iter()
.map(|&v| scirs2_special::gamma::digamma(v))
.collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
#[pyfunction]
fn j1_array_py(py: Python, x: PyReadonlyArray1<f64>) -> PyResult<Py<PyArray1<f64>>> {
let input = x.as_array();
let output: Vec<f64> = input.iter().map(|&v| bessel::j1(v)).collect();
scirs_to_numpy_array1(Array1::from_vec(output), py)
}
pub fn register_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(gamma_py, m)?)?;
m.add_function(wrap_pyfunction!(lgamma_py, m)?)?;
m.add_function(wrap_pyfunction!(digamma_py, m)?)?;
m.add_function(wrap_pyfunction!(beta_py, m)?)?;
m.add_function(wrap_pyfunction!(j0_py, m)?)?;
m.add_function(wrap_pyfunction!(j1_py, m)?)?;
m.add_function(wrap_pyfunction!(jn_py, m)?)?;
m.add_function(wrap_pyfunction!(y0_py, m)?)?;
m.add_function(wrap_pyfunction!(y1_py, m)?)?;
m.add_function(wrap_pyfunction!(yn_py, m)?)?;
m.add_function(wrap_pyfunction!(i0_py, m)?)?;
m.add_function(wrap_pyfunction!(i1_py, m)?)?;
m.add_function(wrap_pyfunction!(k0_py, m)?)?;
m.add_function(wrap_pyfunction!(k1_py, m)?)?;
m.add_function(wrap_pyfunction!(erf_py, m)?)?;
m.add_function(wrap_pyfunction!(erfc_py, m)?)?;
m.add_function(wrap_pyfunction!(erfinv_py, m)?)?;
m.add_function(wrap_pyfunction!(erfcinv_py, m)?)?;
m.add_function(wrap_pyfunction!(erfcx_py, m)?)?;
m.add_function(wrap_pyfunction!(erfi_py, m)?)?;
m.add_function(wrap_pyfunction!(dawsn_py, m)?)?;
m.add_function(wrap_pyfunction!(factorial_py, m)?)?;
m.add_function(wrap_pyfunction!(comb_py, m)?)?;
m.add_function(wrap_pyfunction!(perm_py, m)?)?;
m.add_function(wrap_pyfunction!(ellipk_py, m)?)?;
m.add_function(wrap_pyfunction!(ellipe_py, m)?)?;
m.add_function(wrap_pyfunction!(ellipkinc_py, m)?)?;
m.add_function(wrap_pyfunction!(ellipeinc_py, m)?)?;
m.add_function(wrap_pyfunction!(polygamma_py, m)?)?;
m.add_function(wrap_pyfunction!(zeta_py, m)?)?;
m.add_function(wrap_pyfunction!(hurwitz_zeta_py, m)?)?;
m.add_function(wrap_pyfunction!(zetac_py, m)?)?;
m.add_function(wrap_pyfunction!(hyp0f1_py, m)?)?;
m.add_function(wrap_pyfunction!(hyp1f1_py, m)?)?;
m.add_function(wrap_pyfunction!(hyp2f1_py, m)?)?;
m.add_function(wrap_pyfunction!(hyperu_py, m)?)?;
m.add_function(wrap_pyfunction!(airy_ai_py, m)?)?;
m.add_function(wrap_pyfunction!(airy_aip_py, m)?)?;
m.add_function(wrap_pyfunction!(airy_bi_py, m)?)?;
m.add_function(wrap_pyfunction!(airy_bip_py, m)?)?;
m.add_function(wrap_pyfunction!(sici_si_py, m)?)?;
m.add_function(wrap_pyfunction!(sici_ci_py, m)?)?;
m.add_function(wrap_pyfunction!(shichi_shi_py, m)?)?;
m.add_function(wrap_pyfunction!(shichi_chi_py, m)?)?;
m.add_function(wrap_pyfunction!(betainc_py, m)?)?;
m.add_function(wrap_pyfunction!(betaincinv_py, m)?)?;
m.add_function(wrap_pyfunction!(gamma_array_py, m)?)?;
m.add_function(wrap_pyfunction!(lgamma_array_py, m)?)?;
m.add_function(wrap_pyfunction!(erf_array_py, m)?)?;
m.add_function(wrap_pyfunction!(erfc_array_py, m)?)?;
m.add_function(wrap_pyfunction!(digamma_array_py, m)?)?;
m.add_function(wrap_pyfunction!(j0_array_py, m)?)?;
m.add_function(wrap_pyfunction!(j1_array_py, m)?)?;
Ok(())
}