use crate::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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_e(x, result.as_mut_ptr()) };
(::Value::from(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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erfc_e(x, result.as_mut_ptr()) };
(::Value::from(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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_log_erfc_e(x, result.as_mut_ptr()) };
(::Value::from(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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_Z_e(x, result.as_mut_ptr()) };
(::Value::from(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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_erf_Q_e(x, result.as_mut_ptr()) };
(::Value::from(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) -> (Value, ::types::Result) {
let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
let ret = unsafe { sys::gsl_sf_hazard_e(x, result.as_mut_ptr()) };
(::Value::from(ret), unsafe { result.assume_init() }.into())
}
pub fn str_error(error: ::Value) -> &'static str {
match error {
::Value::Success => "Success",
::Value::Failure => "Failure",
::Value::Continue => "The iteration has not converged yet",
::Value::Domain => "Input domain error",
::Value::Range => "Output range error",
::Value::Fault => "Invalid pointer",
::Value::Invalid => "Invalid argument supplied by user",
::Value::Failed => "generic failure",
::Value::Factorization => "Factorization failed",
::Value::Sanity => "Sanity check failed - shouldn't happen",
::Value::NoMemory => "Malloc failed",
::Value::BadFunction => "Problem with user-supplied function",
::Value::RunAway => "Iterative process is out of control",
::Value::MaxIteration => "Exceeded max number of iterations",
::Value::ZeroDiv => "Tried to divide by zero",
::Value::BadTolerance => "Specified tolerance is invalid or theoretically unattainable",
::Value::Tolerance => "Failed to reach the specified tolerance",
::Value::UnderFlow => "Underflow",
::Value::OverFlow => "Overflow",
::Value::Loss => "Loss of accuracy",
::Value::Round => "Roundoff error",
::Value::BadLength => "Matrix/vector sizes are not conformant",
::Value::NotSquare => "Matrix not square",
::Value::Singularity => "Singularity or extremely bad function behavior detected",
::Value::Diverge => "Integral or series is divergent",
::Value::Unsupported => "The required feature is not supported by this hardware platform",
::Value::Unimplemented => "The requested feature is not (yet) implemented",
::Value::Cache => "Cache limit exceeded",
::Value::Table => "Table limit exceeded",
::Value::NoProgress => "Iteration is not making progress towards solution",
::Value::NoProgressJacobian => "Jacobian evaluations are not improving the solution",
::Value::ToleranceF => "Cannot reach the specified tolerance in F",
::Value::ToleranceX => "Cannot reach the specified tolerance in X",
::Value::ToleranceG => "Cannot reach the specified tolerance in gradient",
::Value::EOF => "End of file",
::Value::Unknown(_) => "Unknown error",
}
}
static mut CALLBACK: Option<fn(&str, &str, u32, ::Value)> = None;
#[doc(alias = "gsl_set_error_handler")]
pub fn set_error_handler(
f: Option<fn(&str, &str, u32, ::Value)>,
) -> Option<fn(&str, &str, u32, ::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, ::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 _,
::Value::from(gsl_errno),
);
}
}
}
#[test]
fn test_error_handler() {
use {bessel, Value};
set_error_handler_off();
match bessel::K0_e(1e3) {
(Value::UnderFlow, r) => println!("K0(1e3) underflowed: {:.3e}", r.val),
_ => panic!("unexpected"),
}
}