rgsl/types/
integration.rs

1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5#![allow(clippy::upper_case_acronyms)]
6
7use crate::enums;
8use crate::Value;
9use ffi::FFI;
10
11ffi_wrapper!(IntegrationFixedType, *const sys::gsl_integration_fixed_type);
12
13impl IntegrationFixedType {
14    #[doc(alias = "gsl_integration_fixed_legendre")]
15    pub fn legendre() -> IntegrationFixedType {
16        ffi_wrap!(gsl_integration_fixed_legendre)
17    }
18    #[doc(alias = "gsl_integration_fixed_chebyshev")]
19    pub fn chebyshev() -> IntegrationFixedType {
20        ffi_wrap!(gsl_integration_fixed_chebyshev)
21    }
22    #[doc(alias = "gsl_integration_fixed_chebyshev2")]
23    pub fn chebyshev2() -> IntegrationFixedType {
24        ffi_wrap!(gsl_integration_fixed_chebyshev2)
25    }
26    #[doc(alias = "gsl_integration_fixed_gegenbauer")]
27    pub fn gegenbauer() -> IntegrationFixedType {
28        ffi_wrap!(gsl_integration_fixed_gegenbauer)
29    }
30    #[doc(alias = "gsl_integration_fixed_jacobi")]
31    pub fn jacobi() -> IntegrationFixedType {
32        ffi_wrap!(gsl_integration_fixed_jacobi)
33    }
34    #[doc(alias = "gsl_integration_fixed_laguerre")]
35    pub fn laguerre() -> IntegrationFixedType {
36        ffi_wrap!(gsl_integration_fixed_laguerre)
37    }
38    #[doc(alias = "gsl_integration_fixed_hermite")]
39    pub fn hermite() -> IntegrationFixedType {
40        ffi_wrap!(gsl_integration_fixed_hermite)
41    }
42    #[doc(alias = "gsl_integration_fixed_exponential")]
43    pub fn exponential() -> IntegrationFixedType {
44        ffi_wrap!(gsl_integration_fixed_exponential)
45    }
46    #[doc(alias = "gsl_integration_fixed_rational")]
47    pub fn rational() -> IntegrationFixedType {
48        ffi_wrap!(gsl_integration_fixed_rational)
49    }
50}
51
52ffi_wrapper!(
53    IntegrationFixedWorkspace,
54    *mut sys::gsl_integration_fixed_workspace,
55    gsl_integration_fixed_free
56);
57
58impl IntegrationFixedWorkspace {
59    #[doc(alias = "gsl_integration_fixed_alloc")]
60    pub fn new(
61        type_: IntegrationFixedType,
62        n: usize,
63        a: f64,
64        b: f64,
65        alpha: f64,
66        beta: f64,
67    ) -> Option<IntegrationFixedWorkspace> {
68        let tmp = unsafe {
69            sys::gsl_integration_fixed_alloc(type_.unwrap_shared(), n, a, b, alpha, beta)
70        };
71
72        if tmp.is_null() {
73            None
74        } else {
75            Some(Self::wrap(tmp))
76        }
77    }
78
79    #[doc(alias = "gsl_integration_fixed_n")]
80    pub fn n(&self) -> usize {
81        unsafe { sys::gsl_integration_fixed_n(self.unwrap_shared()) }
82    }
83
84    #[doc(alias = "gsl_integration_fixed_nodes")]
85    pub fn nodes(&self) -> Option<&[f64]> {
86        let tmp = unsafe { sys::gsl_integration_fixed_nodes(self.unwrap_shared()) };
87        if tmp.is_null() {
88            return None;
89        }
90        unsafe { Some(::std::slice::from_raw_parts(tmp, self.n())) }
91    }
92
93    #[doc(alias = "gsl_integration_fixed_weights")]
94    pub fn weights(&self) -> Option<&[f64]> {
95        let tmp = unsafe { sys::gsl_integration_fixed_weights(self.unwrap_shared()) };
96        if tmp.is_null() {
97            return None;
98        }
99        unsafe { Some(::std::slice::from_raw_parts(tmp, self.n())) }
100    }
101
102    #[doc(alias = "gsl_integration_fixed")]
103    pub fn fixed<F: Fn(f64) -> f64>(&self, f: F) -> Result<f64, Value> {
104        let mut result = 0.;
105        let function = wrap_callback!(f, F);
106
107        let ret =
108            unsafe { sys::gsl_integration_fixed(&function, &mut result, self.unwrap_shared()) };
109        result_handler!(ret, result)
110    }
111}
112
113ffi_wrapper!(IntegrationWorkspace, *mut sys::gsl_integration_workspace, gsl_integration_workspace_free,
114"The QAG algorithm is a simple adaptive integration procedure. The integration region is divided
115into subintervals, and on each iteration the subinterval with the largest estimated error is
116bisected. This reduces the overall error rapidly, as the subintervals become concentrated
117around local difficulties in the integrand. These subintervals are managed by a
118gsl_integration_workspace struct, which handles the memory for the subinterval ranges, results
119and error estimates.");
120
121impl IntegrationWorkspace {
122    /// This function allocates a workspace sufficient to hold n double precision intervals, their
123    /// integration results and error estimates. One workspace may be used multiple times as all
124    /// necessary reinitialization is performed automatically by the integration routines.
125    #[doc(alias = "gsl_integration_workspace_alloc")]
126    pub fn new(n: usize) -> Option<IntegrationWorkspace> {
127        let tmp = unsafe { sys::gsl_integration_workspace_alloc(n) };
128
129        if tmp.is_null() {
130            None
131        } else {
132            Some(Self::wrap(tmp))
133        }
134    }
135
136    pub fn limit(&self) -> usize {
137        unsafe { (*self.unwrap_shared()).limit }
138    }
139    pub fn size(&self) -> usize {
140        unsafe { (*self.unwrap_shared()).size }
141    }
142    pub fn nrmax(&self) -> usize {
143        unsafe { (*self.unwrap_shared()).nrmax }
144    }
145    pub fn i(&self) -> usize {
146        unsafe { (*self.unwrap_shared()).i }
147    }
148    pub fn maximum_level(&self) -> usize {
149        unsafe { (*self.unwrap_shared()).maximum_level }
150    }
151
152    /// This function applies an integration rule adaptively until an estimate of the integral of f
153    /// over (a,b) is achieved within the desired absolute and relative error limits, epsabs and
154    /// epsrel. The function returns the final approximation, result, and an estimate of the
155    /// absolute error, abserr. The integration rule is determined by the value of key, which should
156    /// be chosen from the following symbolic names,
157    ///
158    /// GSL_INTEG_GAUSS15  (key = 1)
159    ///
160    /// GSL_INTEG_GAUSS21  (key = 2)
161    ///
162    /// GSL_INTEG_GAUSS31  (key = 3)
163    ///
164    /// GSL_INTEG_GAUSS41  (key = 4)
165    ///
166    /// GSL_INTEG_GAUSS51  (key = 5)
167    ///
168    /// GSL_INTEG_GAUSS61  (key = 6)
169    ///
170    /// corresponding to the 15f64, 21f64, 31f64, 41f64, 51 and 61 point Gauss-Kronrod rules. The
171    /// higher-order rules give better accuracy for smooth functions, while lower-order rules save
172    /// time when the function contains local difficulties, such as discontinuities.
173    ///
174    /// On each iteration the adaptive integration strategy bisects the interval with the largest
175    /// error estimate. The subintervals and their results are stored in the memory provided by
176    /// workspace. The maximum number of subintervals is given by limit, which may not exceed the
177    /// allocated size of the workspace.
178    ///
179    /// Returns `(result, abs_err)`.
180    #[doc(alias = "gsl_integration_qag")]
181    pub fn qag<F: Fn(f64) -> f64>(
182        &mut self,
183        f: F,
184        a: f64,
185        b: f64,
186        epsabs: f64,
187        epsrel: f64,
188        limit: usize,
189        key: enums::GaussKronrodRule,
190    ) -> Result<(f64, f64), Value> {
191        let mut result = 0.;
192        let mut abs_err = 0.;
193        let function = wrap_callback!(f, F);
194
195        let ret = unsafe {
196            sys::gsl_integration_qag(
197                &function,
198                a,
199                b,
200                epsabs,
201                epsrel,
202                limit,
203                key.into(),
204                self.unwrap_unique(),
205                &mut result,
206                &mut abs_err,
207            )
208        };
209        result_handler!(ret, (result, abs_err))
210    }
211
212    /// This function applies the Gauss-Kronrod 21-point integration rule adaptively until an
213    /// estimate of the integral of f over (a,b) is achieved within the desired absolute and
214    /// relative error limits, epsabs and epsrel. The results are extrapolated using the
215    /// epsilon-algorithm, which accelerates the convergence of the integral in the presence of
216    /// discontinuities and integrable singularities. The function returns the final approximation
217    /// from the extrapolation, result, and an estimate of the absolute error, abserr. The
218    /// subintervals and their results are stored in the memory provided by workspace. The maximum
219    /// number of subintervals is given by limit, which may not exceed the allocated size of the
220    /// workspace.
221    ///
222    /// Returns `(result, abs_err)`.
223    #[doc(alias = "gsl_integration_qags")]
224    pub fn qags<F: Fn(f64) -> f64>(
225        &mut self,
226        f: F,
227        a: f64,
228        b: f64,
229        epsabs: f64,
230        epsrel: f64,
231        limit: usize,
232    ) -> Result<(f64, f64), Value> {
233        let mut result = 0.;
234        let mut abs_err = 0.;
235        let function = wrap_callback!(f, F);
236
237        let ret = unsafe {
238            sys::gsl_integration_qags(
239                &function,
240                a,
241                b,
242                epsabs,
243                epsrel,
244                limit,
245                self.unwrap_unique(),
246                &mut result,
247                &mut abs_err,
248            )
249        };
250        result_handler!(ret, (result, abs_err))
251    }
252
253    /// This function applies the adaptive integration algorithm QAGS taking account of the
254    /// user-supplied locations of singular points. The array pts of length npts should contain the
255    /// endpoints of the integration ranges defined by the integration region and locations of the
256    /// singularities.
257    ///
258    /// For example, to integrate over the region (a,b) with break-points at x_1, x_2, x_3
259    /// (where a < x_1 < x_2 < x_3 < b) the following pts array should be used
260    ///
261    /// ```text
262    /// pts[0] = a
263    /// pts[1] = x_1
264    /// pts[2] = x_2
265    /// pts[3] = x_3
266    /// pts[4] = b
267    /// with npts = 5.
268    /// ```
269    ///
270    /// If you know the locations of the singular points in the integration region then this routine
271    /// will be faster than QAGS.
272    ///
273    /// Returns `(result, abs_err)`.
274    #[doc(alias = "gsl_integration_qagp")]
275    pub fn qagp<F: Fn(f64) -> f64>(
276        &mut self,
277        f: F,
278        pts: &mut [f64],
279        epsabs: f64,
280        epsrel: f64,
281        limit: usize,
282    ) -> Result<(f64, f64), Value> {
283        let mut result = 0.;
284        let mut abs_err = 0.;
285        let function = wrap_callback!(f, F);
286
287        let ret = unsafe {
288            sys::gsl_integration_qagp(
289                &function,
290                pts.as_mut_ptr(),
291                pts.len() as _,
292                epsabs,
293                epsrel,
294                limit,
295                self.unwrap_unique(),
296                &mut result,
297                &mut abs_err,
298            )
299        };
300        result_handler!(ret, (result, abs_err))
301    }
302
303    /// This function computes the integral of the function f over the infinite interval
304    /// `(-\infty,+\infty)`. The integral is mapped onto the semi-open interval `(0,1]` using the
305    /// transformation:
306    ///
307    /// ```text
308    /// x = (1-t)/t,
309    ///
310    /// \int_{-\infty}^{+\infty} dx f(x) =
311    ///      \int_0^1 dt (f((1-t)/t) + f((-1+t)/t))/t^2.
312    /// ```
313    ///
314    /// It is then integrated using the QAGS algorithm. The normal 21-point Gauss-Kronrod rule of
315    /// QAGS is replaced by a 15-point rule, because the transformation can generate an integrable
316    /// singularity at the origin. In this case a lower-order rule is more efficient.
317    ///
318    /// Returns `(result, abs_err)`.
319    #[doc(alias = "gsl_integration_qagi")]
320    pub fn qagi<F: Fn(f64) -> f64>(
321        &mut self,
322        f: F,
323        epsabs: f64,
324        epsrel: f64,
325        limit: usize,
326    ) -> Result<(f64, f64), Value> {
327        let mut result = 0.;
328        let mut abs_err = 0.;
329        let mut function = wrap_callback!(f, F);
330
331        let ret = unsafe {
332            sys::gsl_integration_qagi(
333                &mut function,
334                epsabs,
335                epsrel,
336                limit,
337                self.unwrap_unique(),
338                &mut result,
339                &mut abs_err,
340            )
341        };
342        result_handler!(ret, (result, abs_err))
343    }
344
345    /// This function computes the integral of the function f over the semi-infinite interval
346    /// `(a,+\infty)`. The integral is mapped onto the semi-open interval `(0,1]` using the
347    /// transformation:
348    ///
349    /// ```text
350    /// x = a + (1-t)/t,
351    ///
352    /// \int_{a}^{+\infty} dx f(x) =
353    ///      \int_0^1 dt f(a + (1-t)/t)/t^2
354    /// ```
355    ///
356    /// and then integrated using the QAGS algorithm.
357    ///
358    /// Returns `(result, abs_err)`.
359    #[doc(alias = "gsl_integration_qagiu")]
360    pub fn qagiu<F: Fn(f64) -> f64>(
361        &mut self,
362        f: F,
363        a: f64,
364        epsabs: f64,
365        epsrel: f64,
366        limit: usize,
367    ) -> Result<(f64, f64), Value> {
368        let mut result = 0.;
369        let mut abs_err = 0.;
370        let mut function = wrap_callback!(f, F);
371
372        let ret = unsafe {
373            sys::gsl_integration_qagiu(
374                &mut function,
375                a,
376                epsabs,
377                epsrel,
378                limit,
379                self.unwrap_unique(),
380                &mut result,
381                &mut abs_err,
382            )
383        };
384        result_handler!(ret, (result, abs_err))
385    }
386
387    /// This function computes the integral of the function f over the semi-infinite interval
388    /// `(-\infty,b)`. The integral is mapped onto the semi-open interval `(0,1]` using the
389    /// transformation:
390    ///
391    /// ```text
392    ///  x = b - (1-t)/t,
393    ///
394    /// \int_{-\infty}^{b} dx f(x) =
395    ///      \int_0^1 dt f(b - (1-t)/t)/t^2
396    /// ```
397    ///
398    /// and then integrated using the QAGS algorithm.
399    ///
400    /// Returns `(result, abs_err)`.
401    #[doc(alias = "gsl_integration_qagil")]
402    pub fn qagil<F: Fn(f64) -> f64>(
403        &mut self,
404        f: F,
405        b: f64,
406        epsabs: f64,
407        epsrel: f64,
408        limit: usize,
409    ) -> Result<(f64, f64), Value> {
410        let mut result = 0.;
411        let mut abs_err = 0.;
412        let mut function = wrap_callback!(f, F);
413
414        let ret = unsafe {
415            sys::gsl_integration_qagil(
416                &mut function,
417                b,
418                epsabs,
419                epsrel,
420                limit,
421                self.unwrap_unique(),
422                &mut result,
423                &mut abs_err,
424            )
425        };
426        result_handler!(ret, (result, abs_err))
427    }
428
429    /// This function computes the Cauchy principal value of the integral of f over `(a,b)`, with a
430    /// singularity at c,
431    ///
432    /// ```text
433    /// I = \int_a^b dx f(x) / (x - c)
434    /// ```
435    ///
436    /// The adaptive bisection algorithm of QAG is used, with modifications to ensure that
437    /// subdivisions do not occur at the singular point x = c.
438    ///
439    /// When a subinterval contains the point x = c or is close to it then a special 25-point
440    /// modified Clenshaw-Curtis rule is used to control the singularity. Further away from the
441    /// singularity the algorithm uses an ordinary 15-point Gauss-Kronrod integration rule.
442    ///
443    /// Returns `(result, abs_err)`.
444    #[doc(alias = "gsl_integration_qawc")]
445    pub fn qawc<F: Fn(f64) -> f64>(
446        &mut self,
447        f: F,
448        a: f64,
449        b: f64,
450        c: f64,
451        epsabs: f64,
452        epsrel: f64,
453        limit: usize,
454    ) -> Result<(f64, f64), Value> {
455        let mut result = 0.;
456        let mut abs_err = 0.;
457        let mut function = wrap_callback!(f, F);
458
459        let ret = unsafe {
460            sys::gsl_integration_qawc(
461                &mut function,
462                a,
463                b,
464                c,
465                epsabs,
466                epsrel,
467                limit,
468                self.unwrap_unique(),
469                &mut result,
470                &mut abs_err,
471            )
472        };
473        result_handler!(ret, (result, abs_err))
474    }
475}
476
477ffi_wrapper!(
478    IntegrationQawsTable,
479    *mut sys::gsl_integration_qaws_table,
480    gsl_integration_qaws_table_free,
481    "The QAWS algorithm is designed for integrands with algebraic-logarithmic singularities at the
482end-points of an integration region. In order to work efficiently the algorithm requires a
483precomputed table of Chebyshev moments."
484);
485
486impl IntegrationQawsTable {
487    /// This function allocates space for a gsl_integration_qaws_table struct describing a singular
488    /// weight function W(x) with the parameters `alpha`, `beta`, `mu` and `nu`,
489    ///
490    /// ```text
491    /// W(x) = (x-a)^alpha (b-x)^beta log^mu (x-a) log^nu (b-x)
492    /// ```
493    ///
494    /// where `alpha > -1f64`, `beta > -1f64`, and `mu = 0, 1`, `nu = 0, 1`. The weight function can
495    /// take four different forms depending on the values of `mu` and `nu`,
496    ///
497    /// ```text
498    /// W(x) = (x-a)^alpha (b-x)^beta                   (mu = 0, nu = 0)
499    /// W(x) = (x-a)^alpha (b-x)^beta log(x-a)          (mu = 1, nu = 0)
500    /// W(x) = (x-a)^alpha (b-x)^beta log(b-x)          (mu = 0, nu = 1)
501    /// W(x) = (x-a)^alpha (b-x)^beta log(x-a) log(b-x) (mu = 1, nu = 1)
502    /// ```
503    ///
504    /// The singular points (a,b) do not have to be specified until the integral is computed, where
505    /// they are the endpoints of the integration range.
506    ///
507    /// The function returns a pointer to the newly allocated table gsl_integration_qaws_table if no
508    /// errors were detected, and 0 in the case of error.
509    #[doc(alias = "gsl_integration_qaws_table_alloc")]
510    pub fn new(alpha: f64, beta: f64, mu: i32, nu: i32) -> Option<IntegrationQawsTable> {
511        let tmp = unsafe { sys::gsl_integration_qaws_table_alloc(alpha, beta, mu, nu) };
512
513        if tmp.is_null() {
514            None
515        } else {
516            Some(Self::wrap(tmp))
517        }
518    }
519
520    /// This function modifies the parameters (\alpha, \beta, \mu, \nu)
521    #[doc(alias = "gsl_integration_qaws_table_set")]
522    pub fn set(&mut self, alpha: f64, beta: f64, mu: i32, nu: i32) -> Result<(), Value> {
523        let ret = unsafe {
524            sys::gsl_integration_qaws_table_set(self.unwrap_unique(), alpha, beta, mu, nu)
525        };
526        result_handler!(ret, ())
527    }
528
529    /// This function computes the integral of the function f(x) over the interval (a,b) with the
530    /// singular weight function `(x-a)^\alpha (b-x)^\beta \log^\mu (x-a) \log^\nu (b-x)`. The
531    /// parameters of the weight function (\alpha, \beta, \mu, \nu) are taken from the table self.
532    /// The integral is,
533    ///
534    /// ```text
535    /// I = \int_a^b dx f(x) (x-a)^alpha (b-x)^beta log^mu (x-a) log^nu (b-x).
536    /// ```
537    ///
538    /// The adaptive bisection algorithm of QAG is used. When a subinterval contains one of the
539    /// endpoints then a special 25-point modified Clenshaw-Curtis rule is used to control the
540    /// singularities. For subintervals which do not include the endpoints an ordinary 15-point
541    /// Gauss-Kronrod integration rule is used.
542    ///
543    /// Returns `(result, abs_err)`
544    #[doc(alias = "gsl_integration_qaws")]
545    pub fn qaws<F: Fn(f64) -> f64>(
546        &mut self,
547        f: F,
548        a: f64,
549        b: f64,
550        epsabs: f64,
551        epsrel: f64,
552        limit: usize,
553        workspace: &mut IntegrationWorkspace,
554    ) -> Result<(f64, f64), Value> {
555        let mut result = 0.;
556        let mut abs_err = 0.;
557        let mut function = wrap_callback!(f, F);
558
559        let ret = unsafe {
560            sys::gsl_integration_qaws(
561                &mut function,
562                a,
563                b,
564                self.unwrap_unique(),
565                epsabs,
566                epsrel,
567                limit,
568                workspace.unwrap_unique(),
569                &mut result,
570                &mut abs_err,
571            )
572        };
573        result_handler!(ret, (result, abs_err))
574    }
575}
576
577ffi_wrapper!(
578    IntegrationQawoTable,
579    *mut sys::gsl_integration_qawo_table,
580    gsl_integration_qawo_table_free,
581    "The QAWO algorithm is designed for integrands with an oscillatory factor, `sin(omega x)` or
582`cos(omega x)`. In order to work efficiently the algorithm requires a table of Chebyshev moments
583which must be pre-computed with calls to the functions below."
584);
585
586impl IntegrationQawoTable {
587    /// This function allocates space for a gsl_integration_qawo_table struct and its associated
588    /// workspace describing a sine or cosine weight function W(x) with the parameters (\omega, L),
589    ///
590    /// ```text
591    /// W(x) = sin(omega x)
592    /// W(x) = cos(omega x)
593    /// ```
594    ///
595    /// The parameter L must be the length of the interval over which the function will be
596    /// integrated L = b - a. The choice of sine or cosine is made with the parameter sine which
597    /// should be chosen from one of the two following symbolic values:
598    ///
599    /// ```text
600    /// ::Cosine
601    /// ::IntegrationQawo::Sine
602    /// ```
603    ///
604    /// The gsl_integration_qawo_table is a table of the trigonometric coefficients required in the
605    /// integration process. The parameter n determines the number of levels of coefficients that
606    /// are computed. Each level corresponds to one bisection of the interval L, so that n levels
607    /// are sufficient for subintervals down to the length L/2^n. The integration routine
608    /// gsl_integration_qawo returns the error ::Table if the number of levels is insufficient for
609    /// the requested accuracy.
610    #[doc(alias = "gsl_integration_qawo_table_alloc")]
611    pub fn new(
612        omega: f64,
613        l: f64,
614        sine: ::IntegrationQawo,
615        n: usize,
616    ) -> Option<IntegrationQawoTable> {
617        let tmp = unsafe { sys::gsl_integration_qawo_table_alloc(omega, l, sine.into(), n) };
618
619        if tmp.is_null() {
620            None
621        } else {
622            Some(Self::wrap(tmp))
623        }
624    }
625
626    /// This function changes the parameters omega, L and sine of the existing self workspace.
627    #[doc(alias = "gsl_integration_qawo_table_set")]
628    pub fn set(&mut self, omega: f64, l: f64, sine: ::IntegrationQawo) -> Result<(), Value> {
629        let ret = unsafe {
630            sys::gsl_integration_qawo_table_set(self.unwrap_unique(), omega, l, sine.into())
631        };
632        result_handler!(ret, ())
633    }
634
635    /// This function allows the length parameter l of the self workspace to be changed.
636    #[doc(alias = "gsl_integration_qawo_table_set_length")]
637    pub fn set_length(&mut self, l: f64) -> Result<(), Value> {
638        let ret = unsafe { sys::gsl_integration_qawo_table_set_length(self.unwrap_unique(), l) };
639        result_handler!(ret, ())
640    }
641
642    /// This function uses an adaptive algorithm to compute the integral of f over (a,b) with the
643    /// weight function \sin(\omega x) or \cos(\omega x) defined by the table `wf`,
644    ///
645    /// I = \int_a^b dx f(x) sin(omega x)
646    /// I = \int_a^b dx f(x) cos(omega x)
647    ///
648    /// The results are extrapolated using the epsilon-algorithm to accelerate the convergence of
649    /// the integral. The function returns the final approximation from the extrapolation, result,
650    /// and an estimate of the absolute error, abserr. The subintervals and their results are
651    /// stored in the memory provided by workspace. The maximum number of subintervals is given by
652    /// limit, which may not exceed the allocated size of the workspace.
653    ///
654    /// Those subintervals with “large” widths d where d\omega > 4 are computed using a 25-point
655    /// Clenshaw-Curtis integration rule, which handles the oscillatory behavior. Subintervals with
656    /// a "small" widths where d\omega < 4 are computed using a 15-point Gauss-Kronrod integration.
657    ///
658    /// Returns `(result, abserr)`.
659    #[doc(alias = "gsl_integration_qawo")]
660    pub fn qawo<F: Fn(f64) -> f64>(
661        &mut self,
662        f: F,
663        a: f64,
664        epsabs: f64,
665        epsrel: f64,
666        limit: usize,
667        workspace: &mut IntegrationWorkspace,
668    ) -> Result<(f64, f64), Value> {
669        let mut function = wrap_callback!(f, F);
670        let mut result = 0.;
671        let mut abs_err = 0.;
672
673        let ret = unsafe {
674            sys::gsl_integration_qawo(
675                &mut function,
676                a,
677                epsabs,
678                epsrel,
679                limit,
680                workspace.unwrap_unique(),
681                self.unwrap_unique(),
682                &mut result,
683                &mut abs_err,
684            )
685        };
686        result_handler!(ret, (result, abs_err))
687    }
688}
689
690ffi_wrapper!(CquadWorkspace, *mut sys::gsl_integration_cquad_workspace, gsl_integration_cquad_workspace_free,
691"CQUAD is a new doubly-adaptive general-purpose quadrature routine which can handle most types of
692singularities, non-numerical function values such as Inf or NaN, as well as some divergent
693integrals. It generally requires more function evaluations than the integration routines in
694QUADPACK, yet fails less often for difficult integrands.
695
696The underlying algorithm uses a doubly-adaptive scheme in which Clenshaw-Curtis quadrature rules
697of increasing degree are used to compute the integral in each interval. The L_2-norm of the
698difference between the underlying interpolatory polynomials of two successive rules is used as
699an error estimate. The interval is subdivided if the difference between two successive rules is
700too large or a rule of maximum degree has been reached.");
701
702impl CquadWorkspace {
703    /// This function allocates a workspace sufficient to hold the data for n intervals. The number
704    /// n is not the maximum number of intervals that will be evaluated. If the workspace is full,
705    /// intervals with smaller error estimates will be discarded. A minimum of 3 intervals
706    /// is required and for most functions, a workspace of size 100 is sufficient.
707    #[doc(alias = "gsl_integration_cquad_workspace_alloc")]
708    pub fn new(n: usize) -> Option<CquadWorkspace> {
709        let tmp = unsafe { sys::gsl_integration_cquad_workspace_alloc(n) };
710
711        if tmp.is_null() {
712            None
713        } else {
714            Some(Self::wrap(tmp))
715        }
716    }
717
718    /// This function computes the integral of f over (a,b) within the desired absolute and relative
719    /// error limits, epsabs and epsrel using the CQUAD algorithm. The function returns the final
720    /// approximation, result, an estimate of the absolute error, abserr, and the number of function
721    /// evaluations required, nevals.
722    ///
723    /// The CQUAD algorithm divides the integration region into subintervals, and in each iteration,
724    /// the subinterval with the largest estimated error is processed. The algorithm uses
725    /// Clenshaw-Curits quadrature rules of degree 4, 8, 16 and 32 over 5, 9, 17 and 33 nodes
726    /// respectively. Each interval is initialized with the lowest-degree rule. When an interval is
727    /// processed, the next-higher degree rule is evaluated and an error estimate is computed based
728    /// on the L_2-norm of the difference between the underlying interpolating polynomials of both
729    /// rules. If the highest-degree rule has already been used, or the interpolatory polynomials
730    /// differ significantly, the interval is bisected.
731    ///
732    /// The subintervals and their results are stored in the memory provided by workspace. If the
733    /// error estimate or the number of function evaluations is not needed, the pointers abserr and
734    /// nevals can be set to NULL (not in rgsl).
735    ///
736    /// Returns `(result, abs_err, n_evals)`.
737    #[doc(alias = "gsl_integration_cquad")]
738    pub fn cquad<F: Fn(f64) -> f64>(
739        &mut self,
740        f: F,
741        a: f64,
742        b: f64,
743        epsabs: f64,
744        epsrel: f64,
745    ) -> Result<(f64, f64, usize), Value> {
746        let function = wrap_callback!(f, F);
747        let mut result = 0.;
748        let mut abs_err = 0.;
749        let mut n_evals = 0;
750
751        let ret = unsafe {
752            sys::gsl_integration_cquad(
753                &function,
754                a,
755                b,
756                epsabs,
757                epsrel,
758                self.unwrap_unique(),
759                &mut result,
760                &mut abs_err,
761                &mut n_evals,
762            )
763        };
764        result_handler!(ret, (result, abs_err, n_evals))
765    }
766}
767
768ffi_wrapper!(GLFixedTable, *mut sys::gsl_integration_glfixed_table, gsl_integration_glfixed_table_free,
769"The fixed-order Gauss-Legendre integration routines are provided for fast integration of smooth
770functions with known polynomial order. The n-point Gauss-Legendre rule is exact for polynomials
771of order 2*n-1 or less. For example, these rules are useful when integrating basis functions to
772form mass matrices for the Galerkin method. Unlike other numerical integration routines within
773the library, these routines do not accept absolute or relative error bounds.");
774
775impl GLFixedTable {
776    /// This function determines the Gauss-Legendre abscissae and weights necessary for an n-point
777    /// fixed order integration scheme. If possible, high precision precomputed coefficients are
778    /// used. If precomputed weights are not available, lower precision coefficients are computed
779    /// on the fly.
780    #[doc(alias = "gsl_integration_glfixed_table_alloc")]
781    pub fn new(n: usize) -> Option<GLFixedTable> {
782        let tmp = unsafe { sys::gsl_integration_glfixed_table_alloc(n) };
783
784        if tmp.is_null() {
785            None
786        } else {
787            Some(Self::wrap(tmp))
788        }
789    }
790
791    /// For i in [0, …, t->n - 1], this function obtains the i-th Gauss-Legendre point xi and weight
792    /// wi on the interval [a,b]. The points and weights are ordered by increasing point value. A
793    /// function f may be integrated on [a,b] by summing wi * f(xi) over i.
794    ///
795    /// Returns `(xi, wi)` if it succeeded.
796    #[doc(alias = "gsl_integration_glfixed_point")]
797    pub fn glfixed_point(&self, a: f64, b: f64, i: usize) -> Result<(f64, f64), Value> {
798        let mut xi = 0.;
799        let mut wi = 0.;
800        let ret = unsafe {
801            sys::gsl_integration_glfixed_point(a, b, i, &mut xi, &mut wi, self.unwrap_shared())
802        };
803        result_handler!(ret, (xi, wi))
804    }
805
806    /// This function applies the Gauss-Legendre integration rule contained in table self and
807    /// returns the result.
808    #[doc(alias = "gsl_integration_glfixed")]
809    pub fn glfixed<F: Fn(f64) -> f64>(&self, f: F, a: f64, b: f64) -> f64 {
810        let function = wrap_callback!(f, F);
811        unsafe { sys::gsl_integration_glfixed(&function, a, b, self.unwrap_shared()) }
812    }
813}