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}