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}