use crate::{types, Value};
use std::ffi::CStr;
use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int};
#[doc(alias = "gsl_sf_erf")]
pub fn erf(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_erf(x) }
}
#[doc(alias = "gsl_sf_erf_e")]
pub fn erf_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
#[doc(alias = "gsl_sf_erfc")]
pub fn erfc(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_erfc(x) }
}
#[doc(alias = "gsl_sf_erfc_e")]
pub fn erfc_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erfc_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
#[doc(alias = "gsl_sf_log_erfc")]
pub fn log_erfc(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_log_erfc(x) }
}
#[doc(alias = "gsl_sf_log_erfc_e")]
pub fn log_erfc_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_log_erfc_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
#[doc(alias = "gsl_sf_erf_Z")]
pub fn erf_Z(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_erf_Z(x) }
}
#[doc(alias = "gsl_sf_erf_Z_e")]
pub fn erf_Z_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_Z_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
#[doc(alias = "gsl_sf_erf_Q")]
pub fn erf_Q(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_erf_Q(x) }
}
#[doc(alias = "gsl_sf_erf_Q_e")]
pub fn erf_Q_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_Q_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
#[doc(alias = "gsl_sf_hazard")]
pub fn hazard(x: f64) -> f64 {
unsafe { ::sys::gsl_sf_hazard(x) }
}
#[doc(alias = "gsl_sf_hazard_e")]
pub fn hazard_e(x: f64) -> Result<types::Result, Value> {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_hazard_e(x, result.as_mut_ptr()) };
result_handler!(ret, unsafe { result.assume_init() }.into())
}
pub fn str_error(error: crate::Value) -> &'static str {
match error {
crate::Value::Success => "Success",
crate::Value::Failure => "Failure",
crate::Value::Continue => "The iteration has not converged yet",
crate::Value::Domain => "Input domain error",
crate::Value::Range => "Output range error",
crate::Value::Fault => "Invalid pointer",
crate::Value::Invalid => "Invalid argument supplied by user",
crate::Value::Failed => "generic failure",
crate::Value::Factorization => "Factorization failed",
crate::Value::Sanity => "Sanity check failed - shouldn't happen",
crate::Value::NoMemory => "Malloc failed",
crate::Value::BadFunction => "Problem with user-supplied function",
crate::Value::RunAway => "Iterative process is out of control",
crate::Value::MaxIteration => "Exceeded max number of iterations",
crate::Value::ZeroDiv => "Tried to divide by zero",
crate::Value::BadTolerance => {
"Specified tolerance is invalid or theoretically unattainable"
}
crate::Value::Tolerance => "Failed to reach the specified tolerance",
crate::Value::UnderFlow => "Underflow",
crate::Value::OverFlow => "Overflow",
crate::Value::Loss => "Loss of accuracy",
crate::Value::Round => "Roundoff error",
crate::Value::BadLength => "Matrix/vector sizes are not conformant",
crate::Value::NotSquare => "Matrix not square",
crate::Value::Singularity => "Singularity or extremely bad function behavior detected",
crate::Value::Diverge => "Integral or series is divergent",
crate::Value::Unsupported => {
"The required feature is not supported by this hardware platform"
}
crate::Value::Unimplemented => "The requested feature is not (yet) implemented",
crate::Value::Cache => "Cache limit exceeded",
crate::Value::Table => "Table limit exceeded",
crate::Value::NoProgress => "Iteration is not making progress towards solution",
crate::Value::NoProgressJacobian => "Jacobian evaluations are not improving the solution",
crate::Value::ToleranceF => "Cannot reach the specified tolerance in F",
crate::Value::ToleranceX => "Cannot reach the specified tolerance in X",
crate::Value::ToleranceG => "Cannot reach the specified tolerance in gradient",
crate::Value::EOF => "End of file",
crate::Value::Unknown(_) => "Unknown error",
}
}
static mut CALLBACK: Option<fn(&str, &str, u32, crate::Value)> = None;
#[doc(alias = "gsl_set_error_handler")]
pub fn set_error_handler(
f: Option<fn(&str, &str, u32, crate::Value)>,
) -> Option<fn(&str, &str, u32, crate::Value)> {
unsafe {
let out = CALLBACK.take();
match f {
Some(f) => {
CALLBACK = Some(f);
sys::gsl_set_error_handler(Some(inner_error_handler));
}
None => {
sys::gsl_set_error_handler(None);
}
}
out
}
}
#[doc(alias = "gsl_set_error_handler_off")]
pub fn set_error_handler_off() -> Option<fn(&str, &str, u32, crate::Value)> {
unsafe {
sys::gsl_set_error_handler_off();
CALLBACK.take()
}
}
extern "C" fn inner_error_handler(
reason: *const c_char,
file: *const c_char,
line: c_int,
gsl_errno: c_int,
) {
unsafe {
if let Some(ref call) = CALLBACK {
let s = CStr::from_ptr(reason);
let f = CStr::from_ptr(file);
call(
s.to_str().unwrap_or("Unknown"),
f.to_str().unwrap_or("Unknown"),
line as _,
crate::Value::from(gsl_errno),
);
}
}
}
#[test]
fn test_error_handler() {
use {bessel, Value};
set_error_handler_off();
match bessel::K0_e(1e3) {
Err(Value::UnderFlow) => println!("K0(1e3) underflowed"),
_ => panic!("unexpected"),
}
}