1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
//
// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
//
/*!
# Chebyshev Approximations
This chapter describes routines for computing Chebyshev approximations to univariate functions. A
Chebyshev approximation is a truncation of the series f(x) = \sum c_n T_n(x), where the Chebyshev
polynomials T_n(x) = \cos(n \arccos x) provide an orthogonal basis of polynomials on the interval
[-1,1] with the weight function 1 / \sqrt{1-x^2}. The first few Chebyshev polynomials are,
T_0(x) = 1, T_1(x) = x, T_2(x) = 2 x^2 - 1.
For further information see Abramowitz & Stegun, Chapter 22.
## Definitions
The approximation is made over the range [a,b] using order+1 terms, including the coefficient
`c[0]`. The series is computed using the following convention,
f(x) = (c_0 / 2) + \sum_{n=1} c_n T_n(x)
which is needed when accessing the coefficients directly.
## References and Further Reading
The following paper describes the use of Chebyshev series,
R. Broucke, `Ten Subroutines for the Manipulation of Chebyshev Series [C1] (Algorithm 446)`.
Communications of the ACM 16(4), 254–256 (1973)
!*/
use crate::Value;
use ffi::FFI;
ffi_wrapper!(ChebSeries, *mut sys::gsl_cheb_series, gsl_cheb_free);
impl ChebSeries {
#[doc(alias = "gsl_cheb_alloc")]
pub fn new(n: usize) -> Option<Self> {
let tmp = unsafe { sys::gsl_cheb_alloc(n) };
if tmp.is_null() {
None
} else {
Some(Self::wrap(tmp))
}
}
/// This function computes the Chebyshev approximation cs for the function f over the range
/// (a,b) to the previously specified order. The computation of the Chebyshev approximation is
/// an O(n^2) process, and requires n function evaluations.
#[doc(alias = "gsl_cheb_init")]
pub fn init<F: Fn(f64) -> f64>(&mut self, f: F, a: f64, b: f64) -> Value {
let function = wrap_callback!(f, F);
Value::from(unsafe { sys::gsl_cheb_init(self.unwrap_unique(), &function, a, b) })
}
/// This function returns the order of Chebyshev series cs.
#[doc(alias = "gsl_cheb_order")]
pub fn order(&self) -> usize {
unsafe { sys::gsl_cheb_order(self.unwrap_shared()) }
}
/// This function returns the size of the Chebyshev coefficient array c[] for the Chebyshev
/// series cs.
#[doc(alias = "gsl_cheb_size")]
pub fn size(&self) -> usize {
unsafe { sys::gsl_cheb_size(self.unwrap_shared()) }
}
/// This function evaluates the Chebyshev series cs at a given point x.
#[doc(alias = "gsl_cheb_eval")]
pub fn eval(&self, x: f64) -> f64 {
unsafe { sys::gsl_cheb_eval(self.unwrap_shared(), x) }
}
/// This function computes the Chebyshev series cs at a given point x, estimating both the
/// series result and its absolute error abserr. The error estimate is made from the first
/// neglected term in the series.
///
/// Returns `(result, abs_err)`.
#[doc(alias = "gsl_cheb_eval_err")]
pub fn eval_err(&self, x: f64) -> (Value, f64, f64) {
let mut result = 0.;
let mut abs_err = 0.;
let ret =
unsafe { sys::gsl_cheb_eval_err(self.unwrap_shared(), x, &mut result, &mut abs_err) };
(::Value::from(ret), result, abs_err)
}
/// This function evaluates the Chebyshev series cs at a given point x, to (at most) the given
/// order order.
#[doc(alias = "gsl_cheb_eval_n")]
pub fn eval_n(&self, order: usize, x: f64) -> f64 {
unsafe { sys::gsl_cheb_eval_n(self.unwrap_shared(), order, x) }
}
/// This function evaluates a Chebyshev series cs at a given point x, estimating both the series
/// result and its absolute error abserr, to (at most) the given order order. The error estimate
/// is made from the first neglected term in the series.
///
/// Returns `(result, abs_err)`.
#[doc(alias = "gsl_cheb_eval_n_err")]
pub fn eval_n_err(&self, order: usize, x: f64) -> (Value, f64, f64) {
let mut result = 0.;
let mut abs_err = 0.;
let ret = unsafe {
sys::gsl_cheb_eval_n_err(self.unwrap_shared(), order, x, &mut result, &mut abs_err)
};
(::Value::from(ret), result, abs_err)
}
/// This function computes the derivative of the series cs, storing the derivative coefficients
/// in the previously allocated deriv. The two series cs and deriv must have been allocated with
/// the same order.
#[doc(alias = "gsl_cheb_calc_deriv")]
pub fn calc_deriv(&self, deriv: &mut ChebSeries) -> Value {
Value::from(unsafe {
sys::gsl_cheb_calc_deriv(deriv.unwrap_unique(), self.unwrap_shared())
})
}
/// This function computes the integral of the series cs, storing the integral coefficients in
/// the previously allocated integ. The two series cs and integ must have been allocated with
/// the same order. The lower limit of the integration is taken to be the left hand end of the
/// range a.
#[doc(alias = "gsl_cheb_calc_integ")]
pub fn calc_integ(&self, integ: &mut ChebSeries) -> Value {
Value::from(unsafe {
sys::gsl_cheb_calc_integ(integ.unwrap_unique(), self.unwrap_shared())
})
}
}