1use crate::{types, Value};
8use std::ffi::CStr;
9use std::mem::MaybeUninit;
10use std::os::raw::{c_char, c_int};
11
12#[doc(alias = "gsl_sf_erf")]
14pub fn erf(x: f64) -> f64 {
15 unsafe { ::sys::gsl_sf_erf(x) }
16}
17
18#[doc(alias = "gsl_sf_erf_e")]
20pub fn erf_e(x: f64) -> Result<types::Result, Value> {
21 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
22 let ret = unsafe { sys::gsl_sf_erf_e(x, result.as_mut_ptr()) };
23
24 result_handler!(ret, unsafe { result.assume_init() }.into())
25}
26
27#[doc(alias = "gsl_sf_erfc")]
29pub fn erfc(x: f64) -> f64 {
30 unsafe { ::sys::gsl_sf_erfc(x) }
31}
32
33#[doc(alias = "gsl_sf_erfc_e")]
35pub fn erfc_e(x: f64) -> Result<types::Result, Value> {
36 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
37 let ret = unsafe { sys::gsl_sf_erfc_e(x, result.as_mut_ptr()) };
38
39 result_handler!(ret, unsafe { result.assume_init() }.into())
40}
41
42#[doc(alias = "gsl_sf_log_erfc")]
44pub fn log_erfc(x: f64) -> f64 {
45 unsafe { ::sys::gsl_sf_log_erfc(x) }
46}
47
48#[doc(alias = "gsl_sf_log_erfc_e")]
50pub fn log_erfc_e(x: f64) -> Result<types::Result, Value> {
51 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
52 let ret = unsafe { sys::gsl_sf_log_erfc_e(x, result.as_mut_ptr()) };
53
54 result_handler!(ret, unsafe { result.assume_init() }.into())
55}
56
57#[doc(alias = "gsl_sf_erf_Z")]
59pub fn erf_Z(x: f64) -> f64 {
60 unsafe { ::sys::gsl_sf_erf_Z(x) }
61}
62
63#[doc(alias = "gsl_sf_erf_Z_e")]
65pub fn erf_Z_e(x: f64) -> Result<types::Result, Value> {
66 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
67 let ret = unsafe { sys::gsl_sf_erf_Z_e(x, result.as_mut_ptr()) };
68
69 result_handler!(ret, unsafe { result.assume_init() }.into())
70}
71
72#[doc(alias = "gsl_sf_erf_Q")]
80pub fn erf_Q(x: f64) -> f64 {
81 unsafe { ::sys::gsl_sf_erf_Q(x) }
82}
83
84#[doc(alias = "gsl_sf_erf_Q_e")]
92pub fn erf_Q_e(x: f64) -> Result<types::Result, Value> {
93 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
94 let ret = unsafe { sys::gsl_sf_erf_Q_e(x, result.as_mut_ptr()) };
95
96 result_handler!(ret, unsafe { result.assume_init() }.into())
97}
98
99#[doc(alias = "gsl_sf_hazard")]
101pub fn hazard(x: f64) -> f64 {
102 unsafe { ::sys::gsl_sf_hazard(x) }
103}
104
105#[doc(alias = "gsl_sf_hazard_e")]
107pub fn hazard_e(x: f64) -> Result<types::Result, Value> {
108 let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
109 let ret = unsafe { sys::gsl_sf_hazard_e(x, result.as_mut_ptr()) };
110
111 result_handler!(ret, unsafe { result.assume_init() }.into())
112}
113
114pub fn str_error(error: crate::Value) -> &'static str {
115 match error {
116 crate::Value::Success => "Success",
117 crate::Value::Failure => "Failure",
118 crate::Value::Continue => "The iteration has not converged yet",
119 crate::Value::Domain => "Input domain error",
120 crate::Value::Range => "Output range error",
121 crate::Value::Fault => "Invalid pointer",
122 crate::Value::Invalid => "Invalid argument supplied by user",
123 crate::Value::Failed => "generic failure",
124 crate::Value::Factorization => "Factorization failed",
125 crate::Value::Sanity => "Sanity check failed - shouldn't happen",
126 crate::Value::NoMemory => "Malloc failed",
127 crate::Value::BadFunction => "Problem with user-supplied function",
128 crate::Value::RunAway => "Iterative process is out of control",
129 crate::Value::MaxIteration => "Exceeded max number of iterations",
130 crate::Value::ZeroDiv => "Tried to divide by zero",
131 crate::Value::BadTolerance => {
132 "Specified tolerance is invalid or theoretically unattainable"
133 }
134 crate::Value::Tolerance => "Failed to reach the specified tolerance",
135 crate::Value::UnderFlow => "Underflow",
136 crate::Value::OverFlow => "Overflow",
137 crate::Value::Loss => "Loss of accuracy",
138 crate::Value::Round => "Roundoff error",
139 crate::Value::BadLength => "Matrix/vector sizes are not conformant",
140 crate::Value::NotSquare => "Matrix not square",
141 crate::Value::Singularity => "Singularity or extremely bad function behavior detected",
142 crate::Value::Diverge => "Integral or series is divergent",
143 crate::Value::Unsupported => {
144 "The required feature is not supported by this hardware platform"
145 }
146 crate::Value::Unimplemented => "The requested feature is not (yet) implemented",
147 crate::Value::Cache => "Cache limit exceeded",
148 crate::Value::Table => "Table limit exceeded",
149 crate::Value::NoProgress => "Iteration is not making progress towards solution",
150 crate::Value::NoProgressJacobian => "Jacobian evaluations are not improving the solution",
151 crate::Value::ToleranceF => "Cannot reach the specified tolerance in F",
152 crate::Value::ToleranceX => "Cannot reach the specified tolerance in X",
153 crate::Value::ToleranceG => "Cannot reach the specified tolerance in gradient",
154 crate::Value::EOF => "End of file",
155 crate::Value::Unknown(_) => "Unknown error",
156 }
157}
158
159static mut CALLBACK: Option<fn(&str, &str, u32, crate::Value)> = None;
160
161#[doc(alias = "gsl_set_error_handler")]
200pub fn set_error_handler(
201 f: Option<fn(&str, &str, u32, crate::Value)>,
202) -> Option<fn(&str, &str, u32, crate::Value)> {
203 unsafe {
204 let out = CALLBACK.take();
205 match f {
206 Some(f) => {
207 CALLBACK = Some(f);
208 sys::gsl_set_error_handler(Some(inner_error_handler));
209 }
210 None => {
211 sys::gsl_set_error_handler(None);
212 }
213 }
214 out
215 }
216}
217
218#[doc(alias = "gsl_set_error_handler_off")]
223pub fn set_error_handler_off() -> Option<fn(&str, &str, u32, crate::Value)> {
224 unsafe {
225 sys::gsl_set_error_handler_off();
226 CALLBACK.take()
227 }
228}
229
230extern "C" fn inner_error_handler(
231 reason: *const c_char,
232 file: *const c_char,
233 line: c_int,
234 gsl_errno: c_int,
235) {
236 unsafe {
237 if let Some(ref call) = CALLBACK {
238 let s = CStr::from_ptr(reason);
239 let f = CStr::from_ptr(file);
240 call(
241 s.to_str().unwrap_or("Unknown"),
242 f.to_str().unwrap_or("Unknown"),
243 line as _,
244 crate::Value::from(gsl_errno),
245 );
246 }
247 }
248}
249
250#[test]
251fn test_error_handler() {
252 use {bessel, Value};
253
254 set_error_handler_off();
255 match bessel::K0_e(1e3) {
256 Err(Value::UnderFlow) => println!("K0(1e3) underflowed"),
257 _ => panic!("unexpected"),
258 }
259}