use std::mem::zeroed;
use enums;
use ffi;
use libc;
use std::ffi::CStr;
pub fn erf(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_erf(x) }
}
pub fn erf_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_erf_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
pub fn erfc(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_erfc(x) }
}
pub fn erfc_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_erfc_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
pub fn log_erfc(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_log_erfc(x) }
}
pub fn log_erfc_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_log_erfc_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
pub fn erf_Z(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_erf_Z(x) }
}
pub fn erf_Z_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_erf_Z_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
pub fn erf_Q(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_erf_Q(x) }
}
pub fn erf_Q_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_erf_Q_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
pub fn hazard(x: f64) -> f64 {
unsafe { ::ffi::gsl_sf_hazard(x) }
}
pub fn hazard_e(x: f64) -> (enums::Value, ::types::Result) {
let mut result = unsafe { zeroed::<ffi::gsl_sf_result>() };
let ret = unsafe { ffi::gsl_sf_hazard_e(x, &mut result) };
(enums::Value::from(ret), ::types::Result{val: result.val, err: result.err})
}
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;
pub fn set_error_handler(
f: Option<fn(&str, &str, u32, ::Value)>,
) -> Option<fn(&str, &str, u32, ::Value)> {
let f = f.into();
unsafe {
let out = CALLBACK.take();
match f {
Some(f) => {
CALLBACK = Some(f);
ffi::gsl_set_error_handler(Some(inner_error_handler));
}
None => {
ffi::gsl_set_error_handler(None);
}
}
out
}
}
pub fn set_error_handler_off() -> Option<fn(&str, &str, u32, ::Value)> {
unsafe {
ffi::gsl_set_error_handler_off();
CALLBACK.take()
}
}
extern "C" fn inner_error_handler(
reason: *const libc::c_char,
file: *const libc::c_char,
line: libc::c_int,
gsl_errno: libc::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_else(|_| "Unknown"),
f.to_str().unwrap_or_else(|_| "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"),
}
}