rgsl/types/
chebyshev.rs

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