use ffi;
use enums;
use std::f64::consts::PI;
use num::Float;
use c_vec::CSlice;
pub struct ChebSeries {
c: *mut ffi::gsl_cheb_series,
data: CSlice<f64>
}
impl ChebSeries {
pub fn new(n: u64) -> Option<ChebSeries> {
let tmp = unsafe { ffi::gsl_cheb_alloc(n) };
if tmp.is_null() {
None
} else {
unsafe {
Some(ChebSeries {
c: tmp,
data: CSlice::new((*tmp).c, (*tmp).order as usize + 1)
})
}
}
}
pub fn init<T>(&mut self, func: ::function<T>, a: f64, b: f64, param: &mut T) -> enums::value::Value {
if a >= b {
rgsl_error!("null function interval [a,b]", ::Value::Dom);
::Value::Failure
} else {
unsafe {
(*self.c).a = a;
(*self.c).b = b;
let bma = 0.5 * (b - a);
let bpa = 0.5 * (b + a);
let fac = 2.0 / ((*self.c).order as f64 + 1.0);
let mut tmp_vec = CSlice::new((*self.c).f, (*self.c).order_sp as usize + 1);
for k in 0..((*self.c).order + 1) {
let y = (PI * (k as f64 + 0.5) / ((*self.c).order as f64 + 1f64)).cos();
tmp_vec.as_mut()[k as usize] = func(y * bma + bpa, param);
}
for j in 0..((*self.c).order + 1) {
let mut sum = 0f64;
for k in 0..((*self.c).order + 1) {
sum += tmp_vec.as_ref()[k as usize] * (PI * j as f64 * (k as f64 + 0.5) / ((*self.c).order as f64 + 1f64)).cos();
}
self.data.as_mut()[j as usize] = fac * sum;
}
}
::Value::Success
}
}
pub fn order(&self) -> u64 {
unsafe { ffi::gsl_cheb_order(self.c) }
}
pub fn size(&self) -> u64 {
unsafe { ffi::gsl_cheb_size(self.c) }
}
pub fn as_slice<'r>(&'r self) -> &'r [f64] {
self.data.as_ref()
}
pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [f64] {
self.data.as_mut()
}
pub fn eval(&self, x: f64) -> f64 {
unsafe { ffi::gsl_cheb_eval(self.c, x) }
}
pub fn eval_err(&self, x: f64, result: &mut f64, abs_err: &mut f64) -> enums::value::Value {
unsafe { ffi::gsl_cheb_eval_err(self.c, x, result, abs_err) }
}
pub fn eval_n(&self, order: u64, x: f64) -> f64 {
unsafe { ffi::gsl_cheb_eval_n(self.c, order, x) }
}
pub fn eval_n_err(&self, order: u64, x: f64, result: &mut f64, abs_err: &mut f64) -> enums::value::Value {
unsafe { ffi::gsl_cheb_eval_n_err(self.c, order, x, result, abs_err) }
}
pub fn calc_deriv(&self, deriv: &ChebSeries) -> enums::value::Value {
unsafe { ffi::gsl_cheb_calc_deriv(deriv.c, self.c) }
}
pub fn calc_integ(&self, integ: &ChebSeries) -> enums::value::Value {
unsafe { ffi::gsl_cheb_calc_integ(integ.c, self.c) }
}
}
impl Drop for ChebSeries {
fn drop(&mut self) {
unsafe { ffi::gsl_cheb_free(self.c) };
self.c = ::std::ptr::null_mut();
}
}
impl ffi::FFI<ffi::gsl_cheb_series> for ChebSeries {
fn wrap(c: *mut ffi::gsl_cheb_series) -> ChebSeries {
unsafe {
ChebSeries {
c: c,
data: CSlice::new((*c).c, (*c).order as usize + 1)
}
}
}
fn unwrap(c: &ChebSeries) -> *mut ffi::gsl_cheb_series {
c.c
}
}