numo-gsl-integration 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +20 -19
- data/docs/routines.md +57 -14
- data/ext/numo/gsl/integration/callback.c +15 -0
- data/ext/numo/gsl/integration/cquad.c +1 -0
- data/ext/numo/gsl/integration/fixed.c +190 -0
- data/ext/numo/gsl/integration/glfixed.c +21 -0
- data/ext/numo/gsl/integration/integration.c +8 -0
- data/ext/numo/gsl/integration/integration_internal.h +11 -0
- data/ext/numo/gsl/integration/qagi.c +1 -0
- data/ext/numo/gsl/integration/qagil.c +8 -0
- data/ext/numo/gsl/integration/qagiu.c +8 -0
- data/ext/numo/gsl/integration/qagp.c +34 -0
- data/ext/numo/gsl/integration/qags.c +1 -0
- data/ext/numo/gsl/integration/qawc.c +8 -0
- data/ext/numo/gsl/integration/qawf.c +3 -0
- data/ext/numo/gsl/integration/qawo.c +3 -0
- data/ext/numo/gsl/integration/qaws.c +6 -0
- data/ext/numo/gsl/integration/romberg.c +1 -0
- data/lib/numo/gsl/integration/version.rb +1 -1
- data/sig/numo/gsl/integration.rbs +8 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 24601b3a87462ee4bc6077999599478d3c08776b8da2caa648e56dbfaacec731
|
|
4
|
+
data.tar.gz: 97d7fe3772e374a35ab108ea0a4238fbbceb04598fc2637c3f4d76285cc17f66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86447bf3974787c1067ceecacf700b3583fc2365fb0699f7fac10ed33c54b03c83a9ea5467598c0f9f687222d8ad6fed5c14feeca617d61d7ad39f01accb9ea1
|
|
7
|
+
data.tar.gz: 682f48569710825aac5fd2905dcfcab621abe47cea6f48f332b367d6da1747afe38512d08a6e84e1911b6ccd331d88fdb329b714bfa5619534ed8cea41227708
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.1] - 2026-11-06
|
|
6
|
+
|
|
7
|
+
### Changed in 0.3.1
|
|
8
|
+
|
|
9
|
+
- Simplified the internal handling of fixed quadrature rules without changing the public API.
|
|
10
|
+
|
|
11
|
+
## [0.3.0] - 2026-11-05
|
|
12
|
+
|
|
13
|
+
### Added in 0.3.0
|
|
14
|
+
|
|
15
|
+
- Added fixed point quadrature with Legendre, first- and second-kind Chebyshev, Gegenbauer, Jacobi, Laguerre, Hermite, exponential, and rational rules.
|
|
16
|
+
|
|
5
17
|
## [0.2.0] - 2026-11-05
|
|
6
18
|
|
|
7
19
|
### Changed in 0.2.0
|
|
@@ -22,7 +34,7 @@
|
|
|
22
34
|
|
|
23
35
|
### Added in 0.1.0
|
|
24
36
|
|
|
25
|
-
- Added fixed-order Gauss
|
|
37
|
+
- Added fixed-order Gauss-Legendre integration for smooth functions.
|
|
26
38
|
- Added Romberg integration for smooth functions with function-evaluation counts.
|
|
27
39
|
- Added CQUAD doubly-adaptive integration with function-evaluation counts.
|
|
28
40
|
- Added QAWF adaptive integration for sine- and cosine-weighted Fourier integrals over a semi-infinite interval.
|
data/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Numo::GSL::Integration
|
|
2
2
|
|
|
3
|
-
`numo-gsl-integration` provides numerical integration routines from the [GNU Scientific Library (GSL)](https://www.gnu.org/software/gsl/) under the `Numo::GSL::Integration` namespace. It can be installed and loaded without `numo-gsl` or `numo-gsl-alt
|
|
3
|
+
`numo-gsl-integration` provides numerical integration routines from the [GNU Scientific Library (GSL)](https://www.gnu.org/software/gsl/) under the `Numo::GSL::Integration` namespace. It can be installed and loaded without [`numo-gsl`](https://github.com/ruby-numo/numo-gsl) or [`numo-gsl-alt`](https://github.com/mvz/numo-gsl-alt).
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
7
7
|
- [Ruby](https://www.ruby-lang.org/) 3.2 or later
|
|
8
8
|
- GNU Scientific Library (GSL)
|
|
9
|
-
- `gsl-config` available in `PATH`
|
|
9
|
+
- `gsl-config` available in `PATH`
|
|
10
|
+
|
|
10
11
|
GSL itself must be installed separately.
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
@@ -33,7 +34,6 @@ Load the library:
|
|
|
33
34
|
require "numo/gsl/integration"
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
The native extension defines `Numo::GSL::GslError` and installs a process-wide GSL error handler when it is loaded.
|
|
37
37
|
For example, use `qag` to integrate a function over a finite interval:
|
|
38
38
|
|
|
39
39
|
```ruby
|
|
@@ -44,22 +44,23 @@ end
|
|
|
44
44
|
|
|
45
45
|
## Supported routines
|
|
46
46
|
|
|
47
|
-
| Method | Interval
|
|
48
|
-
| --------- |
|
|
49
|
-
| `qng` | Finite
|
|
50
|
-
| `qag` | Finite
|
|
51
|
-
| `qags` | Finite
|
|
52
|
-
| `qagp` | Finite
|
|
53
|
-
| `qagi` | Infinite
|
|
54
|
-
| `qagiu` | Semi-infinite
|
|
55
|
-
| `qagil` | Semi-infinite
|
|
56
|
-
| `qawc` | Finite
|
|
57
|
-
| `qaws` | Finite
|
|
58
|
-
| `qawo` | Finite
|
|
59
|
-
| `qawf` | Semi-infinite
|
|
60
|
-
| `cquad` | Finite
|
|
61
|
-
| `romberg` | Finite
|
|
62
|
-
| `glfixed` | Finite
|
|
47
|
+
| Method | Interval | Intended use |
|
|
48
|
+
| --------- | -------------- | ---------------------------------------------------------------- |
|
|
49
|
+
| `qng` | Finite | Non-adaptive integration of smooth functions |
|
|
50
|
+
| `qag` | Finite | General-purpose adaptive integration |
|
|
51
|
+
| `qags` | Finite | Functions with integrable singularities or discontinuities |
|
|
52
|
+
| `qagp` | Finite | Known singular or discontinuity points |
|
|
53
|
+
| `qagi` | Infinite | Integration over the entire real line |
|
|
54
|
+
| `qagiu` | Semi-infinite | Integration from a finite lower bound to positive infinity |
|
|
55
|
+
| `qagil` | Semi-infinite | Integration from negative infinity to a finite upper bound |
|
|
56
|
+
| `qawc` | Finite | Cauchy principal value with a known singular point |
|
|
57
|
+
| `qaws` | Finite | Algebraic and logarithmic endpoint singularities |
|
|
58
|
+
| `qawo` | Finite | Sine- or cosine-weighted oscillatory integrals |
|
|
59
|
+
| `qawf` | Semi-infinite | Sine- or cosine-weighted Fourier integrals |
|
|
60
|
+
| `cquad` | Finite | Difficult integrands and endpoint singularities |
|
|
61
|
+
| `romberg` | Finite | Smooth functions with extrapolated trapezoidal integration |
|
|
62
|
+
| `glfixed` | Finite | Fixed-order Gauss-Legendre integration of smooth functions |
|
|
63
|
+
| `fixed` | Rule-dependent | Fixed-order Gaussian quadrature with selectable weight functions |
|
|
63
64
|
|
|
64
65
|
See [Integration routines](docs/routines.md) for parameters and examples.
|
|
65
66
|
|
data/docs/routines.md
CHANGED
|
@@ -94,7 +94,7 @@ result, error = Numo::GSL::Integration.qagp(
|
|
|
94
94
|
end
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
The points must be finite numeric values in strictly increasing order. The array must contain at least two values. A non-array argument or a non-numeric element raises `TypeError`. Too few points, non-finite values, or values that are not strictly increasing raise `ArgumentError` before GSL is called.
|
|
97
|
+
The points must be finite numeric values in strictly increasing order. The array must contain at least two values. A non-array argument or a non-numeric element raises `TypeError`. Too few points, non-finite values, or values that are not strictly increasing raise `ArgumentError` before GSL is called.
|
|
98
98
|
The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
99
99
|
|
|
100
100
|
```ruby
|
|
@@ -181,17 +181,10 @@ end
|
|
|
181
181
|
GSL [QAWC](https://www.gnu.org/software/gsl/doc/html/integration.html#qawc-adaptive-integration-for-cauchy-principal-values) computes the Cauchy principal value (PV) of an integral over a finite interval with a singularity at $c$:
|
|
182
182
|
|
|
183
183
|
```math
|
|
184
|
-
PV \int_a^b \frac{f(x)}{x-c}\,dx
|
|
185
|
-
=
|
|
186
|
-
\lim_{\varepsilon\to 0^+}
|
|
187
|
-
\left(
|
|
188
|
-
\int_a^{c-\varepsilon}\frac{f(x)}{x-c}\,dx
|
|
189
|
-
+
|
|
190
|
-
\int_{c+\varepsilon}^b\frac{f(x)}{x-c}\,dx
|
|
191
|
-
\right)
|
|
184
|
+
PV \int_a^b \frac{f(x)}{x-c}\,dx = \lim_{\varepsilon\to 0^{+}} \left( \int_a^{c-\varepsilon}\frac{f(x)}{x-c}\,dx + \int_{c+\varepsilon}^b\frac{f(x)}{x-c}\,dx \right)
|
|
192
185
|
```
|
|
193
186
|
|
|
194
|
-
The block passed to `Numo::GSL::Integration.qawc` returns $f(x)$. Do not divide the block result by $x - c$; QAWC applies that weight internally.
|
|
187
|
+
The block passed to `Numo::GSL::Integration.qawc` returns $f(x)$. Do not divide the block result by $x - c$; QAWC applies that weight internally.
|
|
195
188
|
The following example uses the default integration options and computes the principal value of `x / (x - 1.0)` over the interval from `0.0` to `2.0`, whose exact value is `2.0`:
|
|
196
189
|
|
|
197
190
|
```ruby
|
|
@@ -224,7 +217,7 @@ GSL [QAWS](https://www.gnu.org/software/gsl/doc/html/integration.html#qaws-adapt
|
|
|
224
217
|
\log^\mu(x-a) \log^\nu(b-x).
|
|
225
218
|
```
|
|
226
219
|
|
|
227
|
-
Call `Numo::GSL::Integration.qaws` with the endpoints `a` and `b`, followed by `alpha`, `beta`, `mu`, and `nu`. The exponents `alpha` and `beta` must be greater than `-1.0`. The logarithmic powers `mu` and `nu` must each be `0` or `1`.
|
|
220
|
+
Call `Numo::GSL::Integration.qaws` with the endpoints `a` and `b`, followed by `alpha`, `beta`, `mu`, and `nu`. The exponents `alpha` and `beta` must be greater than `-1.0`. The logarithmic powers `mu` and `nu` must each be `0` or `1`.
|
|
228
221
|
The block returns the unweighted function $f(x)$. QAWS applies the endpoint weight internally. The following example integrates
|
|
229
222
|
|
|
230
223
|
```math
|
|
@@ -321,12 +314,12 @@ result, evaluations = Numo::GSL::Integration.romberg(0.0, Math::PI) do |x|
|
|
|
321
314
|
end
|
|
322
315
|
```
|
|
323
316
|
|
|
324
|
-
The example integral has an exact value of `2.0`. The `epsabs` and `epsrel` keyword arguments control the requested error limits. The `limit` keyword controls the maximum number of Romberg levels and defaults to `20`. GSL requires at least one level and limits the effective workspace to 30 levels.
|
|
317
|
+
The example integral has an exact value of `2.0`. The `epsabs` and `epsrel` keyword arguments control the requested error limits. The `limit` keyword controls the maximum number of Romberg levels and defaults to `20`. GSL requires at least one level and limits the effective workspace to 30 levels.
|
|
325
318
|
Romberg integration does not return an estimated absolute error. Use CQUAD, QAG, QAGS, or another routine that returns an error estimate when the caller needs one.
|
|
326
319
|
|
|
327
320
|
## GLFIXED integration
|
|
328
321
|
|
|
329
|
-
GSL [fixed-order Gauss
|
|
322
|
+
GSL [fixed-order Gauss-Legendre integration](https://www.gnu.org/software/gsl/doc/html/integration.html#gauss-legendre-integration) provides fast integration of smooth functions when an appropriate polynomial order is known. An `n`-point rule integrates polynomials of degree `2 * n - 1` or less exactly, subject to floating-point precision.
|
|
330
323
|
|
|
331
324
|
```ruby
|
|
332
325
|
result = Numo::GSL::Integration.glfixed(
|
|
@@ -338,5 +331,55 @@ result = Numo::GSL::Integration.glfixed(
|
|
|
338
331
|
end
|
|
339
332
|
```
|
|
340
333
|
|
|
341
|
-
The example integral has an exact value of `1.0 / 5.0`. The `order` keyword controls the number of Gauss
|
|
334
|
+
The example integral has an exact value of `1.0 / 5.0`. The `order` keyword controls the number of Gauss-Legendre points and defaults to `10`. It must be a positive integer.
|
|
342
335
|
GLFIXED returns only the integral. It does not accept absolute or relative error bounds and does not return an error estimate. Use an adaptive routine when the required fixed order is not known in advance.
|
|
336
|
+
|
|
337
|
+
## Fixed point quadratures
|
|
338
|
+
|
|
339
|
+
GSL [fixed point quadratures](https://www.gnu.org/software/gsl/doc/html/integration.html#fixed-point-quadratures) provide fixed-order Gaussian quadrature rules for several weight functions. `Numo::GSL::Integration.fixed` takes a quadrature type, the number of points, and the GSL rule parameters:
|
|
340
|
+
|
|
341
|
+
```ruby
|
|
342
|
+
result = Numo::GSL::Integration.fixed(
|
|
343
|
+
:legendre,
|
|
344
|
+
order: 3,
|
|
345
|
+
a: 0.0,
|
|
346
|
+
b: 1.0
|
|
347
|
+
) do |x|
|
|
348
|
+
x ** 4
|
|
349
|
+
end
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
The example has an exact value of `1.0 / 5.0`. The block returns the unweighted function. For weighted rules, GSL applies the selected weight internally.
|
|
353
|
+
|
|
354
|
+
The supported types and required keyword arguments are:
|
|
355
|
+
|
|
356
|
+
| Type | Required rule parameters | Description |
|
|
357
|
+
| -------------- | ------------------------ | ------------------------------------------------------------ |
|
|
358
|
+
| `:legendre` | — | Gauss-Legendre rule over the finite interval from `a` to `b` |
|
|
359
|
+
| `:chebyshev` | — | First-kind Chebyshev rule over the finite interval |
|
|
360
|
+
| `:chebyshev2` | — | Second-kind Chebyshev rule over the finite interval |
|
|
361
|
+
| `:gegenbauer` | `alpha` | Gegenbauer rule |
|
|
362
|
+
| `:jacobi` | `alpha`, `beta` | Jacobi rule |
|
|
363
|
+
| `:laguerre` | `alpha` | Generalized Laguerre rule |
|
|
364
|
+
| `:hermite` | `alpha` | Generalized Hermite rule |
|
|
365
|
+
| `:exponential` | `alpha` | Exponential rule over a finite interval |
|
|
366
|
+
| `:rational` | `alpha`, `beta` | Rational rule |
|
|
367
|
+
|
|
368
|
+
`order` must be a positive integer. The keywords `a` and `b` are required for every type because they are passed to `gsl_integration_fixed_alloc`; their exact role and valid range depend on the selected GSL rule. The `alpha` and `beta` values must also satisfy the constraints imposed by that rule. Invalid numerical parameters are reported as `Numo::GSL::GslError` by GSL.
|
|
369
|
+
|
|
370
|
+
The following example uses the rational rule. Its parameters satisfy the rule's order-dependent constraints for `order: 3`:
|
|
371
|
+
|
|
372
|
+
```ruby
|
|
373
|
+
result = Numo::GSL::Integration.fixed(
|
|
374
|
+
:rational,
|
|
375
|
+
order: 3,
|
|
376
|
+
a: 0.0,
|
|
377
|
+
b: 1.0,
|
|
378
|
+
alpha: 0.0,
|
|
379
|
+
beta: -7.0
|
|
380
|
+
) do |_x|
|
|
381
|
+
1.0
|
|
382
|
+
end
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
The example result is `1.0 / 6.0`. Fixed point quadratures return only the integral. They do not accept absolute or relative error bounds and do not return an error estimate. Use an adaptive routine when the required order is not known in advance.
|
|
@@ -1,44 +1,59 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
+
|
|
2
3
|
static VALUE integration_call_block(VALUE data) {
|
|
3
4
|
integration_callback_params *params = (integration_callback_params *)data;
|
|
4
5
|
VALUE value;
|
|
6
|
+
|
|
5
7
|
value = rb_funcall(params->block, rb_intern("call"), 1, params->x);
|
|
8
|
+
|
|
6
9
|
return rb_Float(value);
|
|
7
10
|
}
|
|
11
|
+
|
|
8
12
|
void integration_callback_params_init(integration_callback_params *params) {
|
|
9
13
|
params->block = rb_block_proc();
|
|
10
14
|
params->x = Qnil;
|
|
11
15
|
params->exception = Qnil;
|
|
12
16
|
params->state = 0;
|
|
13
17
|
}
|
|
18
|
+
|
|
14
19
|
void integration_function_init(gsl_function *function,
|
|
15
20
|
integration_callback_params *params) {
|
|
16
21
|
integration_callback_params_init(params);
|
|
22
|
+
|
|
17
23
|
function->function = integration_callback;
|
|
18
24
|
function->params = params;
|
|
19
25
|
}
|
|
26
|
+
|
|
20
27
|
double integration_callback(double x, void *data) {
|
|
21
28
|
integration_callback_params *params = data;
|
|
22
29
|
VALUE value;
|
|
30
|
+
|
|
23
31
|
if (params->state != 0) {
|
|
24
32
|
return 0.0;
|
|
25
33
|
}
|
|
34
|
+
|
|
26
35
|
params->x = DBL2NUM(x);
|
|
36
|
+
|
|
27
37
|
value = rb_protect(integration_call_block, (VALUE)params, ¶ms->state);
|
|
38
|
+
|
|
28
39
|
if (params->state != 0) {
|
|
29
40
|
params->exception = rb_errinfo();
|
|
30
41
|
return 0.0;
|
|
31
42
|
}
|
|
43
|
+
|
|
32
44
|
return NUM2DBL(value);
|
|
33
45
|
}
|
|
46
|
+
|
|
34
47
|
void integration_raise_callback_exception(integration_callback_params *params) {
|
|
35
48
|
if (params->state != 0) {
|
|
36
49
|
rb_exc_raise(params->exception);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
52
|
+
|
|
39
53
|
void integration_finish_callback(integration_callback_params *params,
|
|
40
54
|
int state) {
|
|
41
55
|
integration_raise_callback_exception(params);
|
|
56
|
+
|
|
42
57
|
if (state != 0) {
|
|
43
58
|
rb_jump_tag(state);
|
|
44
59
|
}
|
|
@@ -52,6 +52,7 @@ VALUE integration_cquad(int argc, VALUE *argv, VALUE self) {
|
|
|
52
52
|
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
53
53
|
|
|
54
54
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 100);
|
|
55
|
+
|
|
55
56
|
epsabs = parsed_options.epsabs;
|
|
56
57
|
epsrel = parsed_options.epsrel;
|
|
57
58
|
limit = parsed_options.limit;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
enum {
|
|
4
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA = 1 << 0,
|
|
5
|
+
INTEGRATION_FIXED_REQUIRES_BETA = 1 << 1
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
typedef struct {
|
|
9
|
+
ID id;
|
|
10
|
+
const char *name;
|
|
11
|
+
const gsl_integration_fixed_type **type;
|
|
12
|
+
unsigned int requirements;
|
|
13
|
+
} integration_fixed_type_info;
|
|
14
|
+
|
|
15
|
+
typedef struct {
|
|
16
|
+
gsl_function *function;
|
|
17
|
+
const gsl_integration_fixed_type *type;
|
|
18
|
+
size_t order;
|
|
19
|
+
double a;
|
|
20
|
+
double b;
|
|
21
|
+
double alpha;
|
|
22
|
+
double beta;
|
|
23
|
+
gsl_integration_fixed_workspace *workspace;
|
|
24
|
+
double *result;
|
|
25
|
+
} integration_fixed_params;
|
|
26
|
+
|
|
27
|
+
static integration_fixed_type_info integration_fixed_types[] = {
|
|
28
|
+
{0, "legendre", &gsl_integration_fixed_legendre, 0},
|
|
29
|
+
{0, "chebyshev", &gsl_integration_fixed_chebyshev, 0},
|
|
30
|
+
{0, "chebyshev2", &gsl_integration_fixed_chebyshev2, 0},
|
|
31
|
+
{0, "gegenbauer", &gsl_integration_fixed_gegenbauer,
|
|
32
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA},
|
|
33
|
+
{0, "jacobi", &gsl_integration_fixed_jacobi,
|
|
34
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA | INTEGRATION_FIXED_REQUIRES_BETA},
|
|
35
|
+
{0, "laguerre", &gsl_integration_fixed_laguerre,
|
|
36
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA},
|
|
37
|
+
{0, "hermite", &gsl_integration_fixed_hermite,
|
|
38
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA},
|
|
39
|
+
{0, "exponential", &gsl_integration_fixed_exponential,
|
|
40
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA},
|
|
41
|
+
{0, "rational", &gsl_integration_fixed_rational,
|
|
42
|
+
INTEGRATION_FIXED_REQUIRES_ALPHA | INTEGRATION_FIXED_REQUIRES_BETA},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
static ID integration_fixed_id_order;
|
|
46
|
+
static ID integration_fixed_id_a;
|
|
47
|
+
static ID integration_fixed_id_b;
|
|
48
|
+
static ID integration_fixed_id_alpha;
|
|
49
|
+
static ID integration_fixed_id_beta;
|
|
50
|
+
static ID integration_fixed_id_less_than_or_equal;
|
|
51
|
+
|
|
52
|
+
void integration_fixed_init(void) {
|
|
53
|
+
size_t i;
|
|
54
|
+
|
|
55
|
+
for (i = 0;
|
|
56
|
+
i < sizeof(integration_fixed_types) / sizeof(integration_fixed_types[0]);
|
|
57
|
+
++i) {
|
|
58
|
+
integration_fixed_types[i].id = rb_intern(integration_fixed_types[i].name);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
integration_fixed_id_order = rb_intern("order");
|
|
62
|
+
integration_fixed_id_a = rb_intern("a");
|
|
63
|
+
integration_fixed_id_b = rb_intern("b");
|
|
64
|
+
integration_fixed_id_alpha = rb_intern("alpha");
|
|
65
|
+
integration_fixed_id_beta = rb_intern("beta");
|
|
66
|
+
integration_fixed_id_less_than_or_equal = rb_intern("<=");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static const integration_fixed_type_info *integration_fixed_type(VALUE type) {
|
|
70
|
+
ID type_id;
|
|
71
|
+
size_t i;
|
|
72
|
+
|
|
73
|
+
if (!RB_TYPE_P(type, T_SYMBOL)) {
|
|
74
|
+
rb_raise(rb_eTypeError, "type must be a Symbol");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type_id = SYM2ID(type);
|
|
78
|
+
for (i = 0;
|
|
79
|
+
i < sizeof(integration_fixed_types) / sizeof(integration_fixed_types[0]);
|
|
80
|
+
++i) {
|
|
81
|
+
if (integration_fixed_types[i].id == type_id) {
|
|
82
|
+
return &integration_fixed_types[i];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
rb_raise(rb_eArgError, "unsupported fixed quadrature type: %s",
|
|
87
|
+
rb_id2name(type_id));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static VALUE integration_free_fixed_workspace(VALUE data) {
|
|
91
|
+
integration_fixed_params *params = (integration_fixed_params *)data;
|
|
92
|
+
|
|
93
|
+
if (params->workspace != NULL) {
|
|
94
|
+
gsl_integration_fixed_free(params->workspace);
|
|
95
|
+
}
|
|
96
|
+
return Qnil;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static VALUE integration_run_fixed(VALUE data) {
|
|
100
|
+
integration_fixed_params *params = (integration_fixed_params *)data;
|
|
101
|
+
|
|
102
|
+
params->workspace =
|
|
103
|
+
gsl_integration_fixed_alloc(params->type, params->order, params->a,
|
|
104
|
+
params->b, params->alpha, params->beta);
|
|
105
|
+
if (params->workspace == NULL) {
|
|
106
|
+
rb_memerror();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
(void)gsl_integration_fixed(params->function, params->result,
|
|
110
|
+
params->workspace);
|
|
111
|
+
return Qnil;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static VALUE integration_run_fixed_with_workspace(VALUE data) {
|
|
115
|
+
return rb_ensure(integration_run_fixed, data,
|
|
116
|
+
integration_free_fixed_workspace, data);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
VALUE integration_fixed(int argc, VALUE *argv, VALUE self) {
|
|
120
|
+
VALUE type;
|
|
121
|
+
VALUE options;
|
|
122
|
+
ID keywords[] = {integration_fixed_id_order, integration_fixed_id_a,
|
|
123
|
+
integration_fixed_id_b, integration_fixed_id_alpha,
|
|
124
|
+
integration_fixed_id_beta};
|
|
125
|
+
VALUE keyword_values[5];
|
|
126
|
+
VALUE order_value;
|
|
127
|
+
VALUE alpha_value;
|
|
128
|
+
VALUE beta_value;
|
|
129
|
+
const integration_fixed_type_info *type_info;
|
|
130
|
+
size_t order;
|
|
131
|
+
gsl_function function;
|
|
132
|
+
integration_callback_params params;
|
|
133
|
+
integration_fixed_params fixed_params = {0};
|
|
134
|
+
double result;
|
|
135
|
+
int state = 0;
|
|
136
|
+
|
|
137
|
+
(void)self;
|
|
138
|
+
rb_scan_args(argc, argv, "1:", &type, &options);
|
|
139
|
+
type_info = integration_fixed_type(type);
|
|
140
|
+
|
|
141
|
+
if (NIL_P(options)) {
|
|
142
|
+
options = rb_hash_new();
|
|
143
|
+
}
|
|
144
|
+
rb_get_kwargs(options, keywords, 3, 2, keyword_values);
|
|
145
|
+
|
|
146
|
+
order_value = keyword_values[0];
|
|
147
|
+
alpha_value = keyword_values[3];
|
|
148
|
+
beta_value = keyword_values[4];
|
|
149
|
+
|
|
150
|
+
if (!RB_INTEGER_TYPE_P(order_value)) {
|
|
151
|
+
rb_raise(rb_eTypeError, "order must be an Integer");
|
|
152
|
+
}
|
|
153
|
+
if (RTEST(rb_funcall(order_value, integration_fixed_id_less_than_or_equal, 1,
|
|
154
|
+
INT2FIX(0)))) {
|
|
155
|
+
rb_raise(rb_eArgError, "order must be positive");
|
|
156
|
+
}
|
|
157
|
+
order = NUM2SIZET(order_value);
|
|
158
|
+
|
|
159
|
+
if ((type_info->requirements & INTEGRATION_FIXED_REQUIRES_ALPHA) != 0 &&
|
|
160
|
+
alpha_value == Qundef) {
|
|
161
|
+
rb_raise(rb_eArgError, "alpha is required for %s", type_info->name);
|
|
162
|
+
}
|
|
163
|
+
if ((type_info->requirements & INTEGRATION_FIXED_REQUIRES_BETA) != 0 &&
|
|
164
|
+
beta_value == Qundef) {
|
|
165
|
+
rb_raise(rb_eArgError, "beta is required for %s", type_info->name);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
integration_function_init(&function, ¶ms);
|
|
169
|
+
fixed_params.function = &function;
|
|
170
|
+
fixed_params.type = *type_info->type;
|
|
171
|
+
fixed_params.order = order;
|
|
172
|
+
fixed_params.a = NUM2DBL(keyword_values[1]);
|
|
173
|
+
fixed_params.b = NUM2DBL(keyword_values[2]);
|
|
174
|
+
fixed_params.alpha =
|
|
175
|
+
(type_info->requirements & INTEGRATION_FIXED_REQUIRES_ALPHA) != 0
|
|
176
|
+
? NUM2DBL(alpha_value)
|
|
177
|
+
: 0.0;
|
|
178
|
+
fixed_params.beta =
|
|
179
|
+
(type_info->requirements & INTEGRATION_FIXED_REQUIRES_BETA) != 0
|
|
180
|
+
? NUM2DBL(beta_value)
|
|
181
|
+
: 0.0;
|
|
182
|
+
fixed_params.result = &result;
|
|
183
|
+
|
|
184
|
+
rb_protect(integration_run_fixed_with_workspace, (VALUE)&fixed_params,
|
|
185
|
+
&state);
|
|
186
|
+
RB_GC_GUARD(params.block);
|
|
187
|
+
RB_GC_GUARD(params.exception);
|
|
188
|
+
integration_finish_callback(¶ms, state);
|
|
189
|
+
return DBL2NUM(result);
|
|
190
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
+
|
|
2
3
|
typedef struct {
|
|
3
4
|
gsl_function *function;
|
|
4
5
|
double a;
|
|
@@ -7,17 +8,23 @@ typedef struct {
|
|
|
7
8
|
gsl_integration_glfixed_table *table;
|
|
8
9
|
double *result;
|
|
9
10
|
} integration_glfixed_params;
|
|
11
|
+
|
|
10
12
|
static VALUE integration_run_glfixed(VALUE data) {
|
|
11
13
|
integration_glfixed_params *params = (integration_glfixed_params *)data;
|
|
14
|
+
|
|
12
15
|
*(params->result) = gsl_integration_glfixed(params->function, params->a,
|
|
13
16
|
params->b, params->table);
|
|
17
|
+
|
|
14
18
|
return Qnil;
|
|
15
19
|
}
|
|
20
|
+
|
|
16
21
|
static VALUE integration_run_glfixed_with_table(VALUE data) {
|
|
17
22
|
integration_glfixed_params *params = (integration_glfixed_params *)data;
|
|
23
|
+
|
|
18
24
|
return rb_ensure(integration_run_glfixed, data,
|
|
19
25
|
integration_free_glfixed_table, (VALUE)params->table);
|
|
20
26
|
}
|
|
27
|
+
|
|
21
28
|
VALUE integration_glfixed(int argc, VALUE *argv, VALUE self) {
|
|
22
29
|
VALUE a;
|
|
23
30
|
VALUE b;
|
|
@@ -31,34 +38,48 @@ VALUE integration_glfixed(int argc, VALUE *argv, VALUE self) {
|
|
|
31
38
|
integration_glfixed_params glfixed_params;
|
|
32
39
|
double result;
|
|
33
40
|
int state = 0;
|
|
41
|
+
|
|
34
42
|
(void)self;
|
|
43
|
+
|
|
35
44
|
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
45
|
+
|
|
36
46
|
if (!NIL_P(options)) {
|
|
37
47
|
rb_get_kwargs(options, keywords, 0, 1, keyword_values);
|
|
38
48
|
order_value = keyword_values[0];
|
|
39
49
|
}
|
|
50
|
+
|
|
40
51
|
if (order_value == Qundef) {
|
|
41
52
|
order = 10;
|
|
42
53
|
} else {
|
|
43
54
|
if (!RB_INTEGER_TYPE_P(order_value)) {
|
|
44
55
|
rb_raise(rb_eTypeError, "order must be an Integer");
|
|
45
56
|
}
|
|
57
|
+
|
|
46
58
|
if (RTEST(rb_funcall(order_value, rb_intern("<="), 1, INT2FIX(0)))) {
|
|
47
59
|
rb_raise(rb_eArgError, "order must be positive");
|
|
48
60
|
}
|
|
61
|
+
|
|
49
62
|
order = NUM2SIZET(order_value);
|
|
50
63
|
}
|
|
64
|
+
|
|
51
65
|
integration_function_init(&function, ¶ms);
|
|
66
|
+
|
|
52
67
|
glfixed_params.function = &function;
|
|
53
68
|
glfixed_params.a = NUM2DBL(a);
|
|
54
69
|
glfixed_params.b = NUM2DBL(b);
|
|
55
70
|
glfixed_params.order = order;
|
|
71
|
+
|
|
56
72
|
glfixed_params.table = gsl_integration_glfixed_table_alloc(order);
|
|
73
|
+
|
|
57
74
|
glfixed_params.result = &result;
|
|
75
|
+
|
|
58
76
|
rb_protect(integration_run_glfixed_with_table, (VALUE)&glfixed_params,
|
|
59
77
|
&state);
|
|
78
|
+
|
|
60
79
|
RB_GC_GUARD(params.block);
|
|
61
80
|
RB_GC_GUARD(params.exception);
|
|
81
|
+
|
|
62
82
|
integration_finish_callback(¶ms, state);
|
|
83
|
+
|
|
63
84
|
return DBL2NUM(result);
|
|
64
85
|
}
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
+
|
|
2
3
|
static VALUE numo_eGslError;
|
|
4
|
+
|
|
3
5
|
static _Noreturn void integration_gsl_error_handler(const char *reason,
|
|
4
6
|
const char *file, int line,
|
|
5
7
|
int gsl_errno) {
|
|
6
8
|
rb_raise(numo_eGslError, "%s:%d: %s (GSL error %d)", file, line, reason,
|
|
7
9
|
gsl_errno);
|
|
8
10
|
}
|
|
11
|
+
|
|
9
12
|
void Init_integration(void) {
|
|
10
13
|
VALUE mNumo;
|
|
11
14
|
VALUE mGSL;
|
|
12
15
|
VALUE mIntegration;
|
|
16
|
+
|
|
13
17
|
mNumo = rb_define_module("Numo");
|
|
14
18
|
mGSL = rb_define_module_under(mNumo, "GSL");
|
|
15
19
|
mIntegration = rb_define_module_under(mGSL, "Integration");
|
|
16
20
|
numo_eGslError = rb_define_class_under(mGSL, "GslError", rb_eStandardError);
|
|
17
21
|
gsl_set_error_handler(&integration_gsl_error_handler);
|
|
22
|
+
integration_fixed_init();
|
|
23
|
+
|
|
18
24
|
rb_define_const(mIntegration, "GAUSS15", INT2NUM(GSL_INTEG_GAUSS15));
|
|
19
25
|
rb_define_const(mIntegration, "GAUSS21", INT2NUM(GSL_INTEG_GAUSS21));
|
|
20
26
|
rb_define_const(mIntegration, "GAUSS31", INT2NUM(GSL_INTEG_GAUSS31));
|
|
@@ -23,6 +29,7 @@ void Init_integration(void) {
|
|
|
23
29
|
rb_define_const(mIntegration, "GAUSS61", INT2NUM(GSL_INTEG_GAUSS61));
|
|
24
30
|
rb_define_const(mIntegration, "COSINE", INT2NUM(GSL_INTEG_COSINE));
|
|
25
31
|
rb_define_const(mIntegration, "SINE", INT2NUM(GSL_INTEG_SINE));
|
|
32
|
+
|
|
26
33
|
rb_define_singleton_method(mIntegration, "qag", integration_qag, -1);
|
|
27
34
|
rb_define_singleton_method(mIntegration, "qng", integration_qng, -1);
|
|
28
35
|
rb_define_singleton_method(mIntegration, "qags", integration_qags, -1);
|
|
@@ -37,4 +44,5 @@ void Init_integration(void) {
|
|
|
37
44
|
rb_define_singleton_method(mIntegration, "cquad", integration_cquad, -1);
|
|
38
45
|
rb_define_singleton_method(mIntegration, "romberg", integration_romberg, -1);
|
|
39
46
|
rb_define_singleton_method(mIntegration, "glfixed", integration_glfixed, -1);
|
|
47
|
+
rb_define_singleton_method(mIntegration, "fixed", integration_fixed, -1);
|
|
40
48
|
}
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
#ifndef NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
2
2
|
#define NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
3
|
+
|
|
3
4
|
#include <gsl/gsl_errno.h>
|
|
4
5
|
#include <gsl/gsl_integration.h>
|
|
5
6
|
#include <ruby.h>
|
|
7
|
+
|
|
6
8
|
typedef struct {
|
|
7
9
|
double epsabs;
|
|
8
10
|
double epsrel;
|
|
9
11
|
size_t limit;
|
|
10
12
|
} integration_options;
|
|
13
|
+
|
|
11
14
|
void integration_options_parse(VALUE options, integration_options *parsed,
|
|
12
15
|
double default_epsabs, double default_epsrel,
|
|
13
16
|
size_t default_limit);
|
|
17
|
+
|
|
14
18
|
typedef struct {
|
|
15
19
|
VALUE block;
|
|
16
20
|
VALUE x;
|
|
17
21
|
VALUE exception;
|
|
18
22
|
int state;
|
|
19
23
|
} integration_callback_params;
|
|
24
|
+
|
|
20
25
|
void integration_callback_params_init(integration_callback_params *params);
|
|
21
26
|
void integration_function_init(gsl_function *function,
|
|
22
27
|
integration_callback_params *params);
|
|
@@ -24,10 +29,14 @@ double integration_callback(double x, void *data);
|
|
|
24
29
|
void integration_raise_callback_exception(integration_callback_params *params);
|
|
25
30
|
void integration_finish_callback(integration_callback_params *params,
|
|
26
31
|
int state);
|
|
32
|
+
|
|
27
33
|
VALUE integration_free_workspace(VALUE data);
|
|
28
34
|
VALUE integration_free_cquad_workspace(VALUE data);
|
|
29
35
|
VALUE integration_free_romberg_workspace(VALUE data);
|
|
30
36
|
VALUE integration_free_glfixed_table(VALUE data);
|
|
37
|
+
|
|
38
|
+
void integration_fixed_init(void);
|
|
39
|
+
|
|
31
40
|
VALUE integration_qag(int argc, VALUE *argv, VALUE self);
|
|
32
41
|
VALUE integration_qng(int argc, VALUE *argv, VALUE self);
|
|
33
42
|
VALUE integration_qags(int argc, VALUE *argv, VALUE self);
|
|
@@ -42,4 +51,6 @@ VALUE integration_qawf(int argc, VALUE *argv, VALUE self);
|
|
|
42
51
|
VALUE integration_cquad(int argc, VALUE *argv, VALUE self);
|
|
43
52
|
VALUE integration_romberg(int argc, VALUE *argv, VALUE self);
|
|
44
53
|
VALUE integration_glfixed(int argc, VALUE *argv, VALUE self);
|
|
54
|
+
VALUE integration_fixed(int argc, VALUE *argv, VALUE self);
|
|
55
|
+
|
|
45
56
|
#endif
|
|
@@ -46,6 +46,7 @@ VALUE integration_qagi(int argc, VALUE *argv, VALUE self) {
|
|
|
46
46
|
rb_scan_args(argc, argv, "0:", &options);
|
|
47
47
|
|
|
48
48
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
49
|
+
|
|
49
50
|
epsabs = parsed_options.epsabs;
|
|
50
51
|
epsrel = parsed_options.epsrel;
|
|
51
52
|
limit = parsed_options.limit;
|
|
@@ -13,14 +13,17 @@ typedef struct {
|
|
|
13
13
|
|
|
14
14
|
static VALUE integration_run_qagil(VALUE data) {
|
|
15
15
|
integration_qagil_params *params = (integration_qagil_params *)data;
|
|
16
|
+
|
|
16
17
|
(void)gsl_integration_qagil(params->function, params->b, params->epsabs,
|
|
17
18
|
params->epsrel, params->limit, params->workspace,
|
|
18
19
|
params->result, params->error);
|
|
20
|
+
|
|
19
21
|
return Qnil;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
static VALUE integration_run_qagil_with_workspace(VALUE data) {
|
|
23
25
|
integration_qagil_params *params = (integration_qagil_params *)data;
|
|
26
|
+
|
|
24
27
|
return rb_ensure(integration_run_qagil, data, integration_free_workspace,
|
|
25
28
|
(VALUE)params->workspace);
|
|
26
29
|
}
|
|
@@ -39,11 +42,13 @@ VALUE integration_qagil(int argc, VALUE *argv, VALUE self) {
|
|
|
39
42
|
double result;
|
|
40
43
|
double error;
|
|
41
44
|
int state = 0;
|
|
45
|
+
|
|
42
46
|
(void)self;
|
|
43
47
|
|
|
44
48
|
rb_scan_args(argc, argv, "1:", &b, &options);
|
|
45
49
|
|
|
46
50
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
51
|
+
|
|
47
52
|
epsabs = parsed_options.epsabs;
|
|
48
53
|
epsrel = parsed_options.epsrel;
|
|
49
54
|
limit = parsed_options.limit;
|
|
@@ -51,6 +56,7 @@ VALUE integration_qagil(int argc, VALUE *argv, VALUE self) {
|
|
|
51
56
|
integration_function_init(&function, ¶ms);
|
|
52
57
|
|
|
53
58
|
workspace = gsl_integration_workspace_alloc(limit);
|
|
59
|
+
|
|
54
60
|
qagil_params.function = &function;
|
|
55
61
|
qagil_params.b = NUM2DBL(b);
|
|
56
62
|
qagil_params.epsabs = epsabs;
|
|
@@ -62,8 +68,10 @@ VALUE integration_qagil(int argc, VALUE *argv, VALUE self) {
|
|
|
62
68
|
|
|
63
69
|
rb_protect(integration_run_qagil_with_workspace, (VALUE)&qagil_params,
|
|
64
70
|
&state);
|
|
71
|
+
|
|
65
72
|
RB_GC_GUARD(params.block);
|
|
66
73
|
RB_GC_GUARD(params.exception);
|
|
74
|
+
|
|
67
75
|
integration_finish_callback(¶ms, state);
|
|
68
76
|
|
|
69
77
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
@@ -13,14 +13,17 @@ typedef struct {
|
|
|
13
13
|
|
|
14
14
|
static VALUE integration_run_qagiu(VALUE data) {
|
|
15
15
|
integration_qagiu_params *params = (integration_qagiu_params *)data;
|
|
16
|
+
|
|
16
17
|
(void)gsl_integration_qagiu(params->function, params->a, params->epsabs,
|
|
17
18
|
params->epsrel, params->limit, params->workspace,
|
|
18
19
|
params->result, params->error);
|
|
20
|
+
|
|
19
21
|
return Qnil;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
static VALUE integration_run_qagiu_with_workspace(VALUE data) {
|
|
23
25
|
integration_qagiu_params *params = (integration_qagiu_params *)data;
|
|
26
|
+
|
|
24
27
|
return rb_ensure(integration_run_qagiu, data, integration_free_workspace,
|
|
25
28
|
(VALUE)params->workspace);
|
|
26
29
|
}
|
|
@@ -39,11 +42,13 @@ VALUE integration_qagiu(int argc, VALUE *argv, VALUE self) {
|
|
|
39
42
|
double result;
|
|
40
43
|
double error;
|
|
41
44
|
int state = 0;
|
|
45
|
+
|
|
42
46
|
(void)self;
|
|
43
47
|
|
|
44
48
|
rb_scan_args(argc, argv, "1:", &a, &options);
|
|
45
49
|
|
|
46
50
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
51
|
+
|
|
47
52
|
epsabs = parsed_options.epsabs;
|
|
48
53
|
epsrel = parsed_options.epsrel;
|
|
49
54
|
limit = parsed_options.limit;
|
|
@@ -51,6 +56,7 @@ VALUE integration_qagiu(int argc, VALUE *argv, VALUE self) {
|
|
|
51
56
|
integration_function_init(&function, ¶ms);
|
|
52
57
|
|
|
53
58
|
workspace = gsl_integration_workspace_alloc(limit);
|
|
59
|
+
|
|
54
60
|
qagiu_params.function = &function;
|
|
55
61
|
qagiu_params.a = NUM2DBL(a);
|
|
56
62
|
qagiu_params.epsabs = epsabs;
|
|
@@ -62,8 +68,10 @@ VALUE integration_qagiu(int argc, VALUE *argv, VALUE self) {
|
|
|
62
68
|
|
|
63
69
|
rb_protect(integration_run_qagiu_with_workspace, (VALUE)&qagiu_params,
|
|
64
70
|
&state);
|
|
71
|
+
|
|
65
72
|
RB_GC_GUARD(params.block);
|
|
66
73
|
RB_GC_GUARD(params.exception);
|
|
74
|
+
|
|
67
75
|
integration_finish_callback(¶ms, state);
|
|
68
76
|
|
|
69
77
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
2
|
#include <math.h>
|
|
3
|
+
|
|
3
4
|
typedef struct {
|
|
4
5
|
VALUE points_array;
|
|
5
6
|
gsl_function *function;
|
|
@@ -12,62 +13,84 @@ typedef struct {
|
|
|
12
13
|
double *result;
|
|
13
14
|
double *error;
|
|
14
15
|
} integration_qagp_params;
|
|
16
|
+
|
|
15
17
|
static void integration_validate_qagp_points(VALUE points) {
|
|
16
18
|
long point_count;
|
|
17
19
|
long index;
|
|
18
20
|
double previous = 0.0;
|
|
21
|
+
|
|
19
22
|
if (!RB_TYPE_P(points, T_ARRAY)) {
|
|
20
23
|
rb_raise(rb_eTypeError, "points must be an Array");
|
|
21
24
|
}
|
|
25
|
+
|
|
22
26
|
point_count = RARRAY_LEN(points);
|
|
27
|
+
|
|
23
28
|
if (point_count < 2) {
|
|
24
29
|
rb_raise(rb_eArgError, "points must contain at least two values");
|
|
25
30
|
}
|
|
31
|
+
|
|
26
32
|
for (index = 0; index < point_count; index++) {
|
|
27
33
|
VALUE point = rb_ary_entry(points, index);
|
|
28
34
|
double current;
|
|
35
|
+
|
|
29
36
|
if (!rb_obj_is_kind_of(point, rb_cNumeric)) {
|
|
30
37
|
rb_raise(rb_eTypeError, "points must contain only numeric values");
|
|
31
38
|
}
|
|
39
|
+
|
|
32
40
|
current = NUM2DBL(point);
|
|
41
|
+
|
|
33
42
|
if (!isfinite(current)) {
|
|
34
43
|
rb_raise(rb_eArgError, "points must contain only finite values");
|
|
35
44
|
}
|
|
45
|
+
|
|
36
46
|
if (index > 0 && !(previous < current)) {
|
|
37
47
|
rb_raise(rb_eArgError, "points must be strictly increasing");
|
|
38
48
|
}
|
|
49
|
+
|
|
39
50
|
previous = current;
|
|
40
51
|
}
|
|
41
52
|
}
|
|
53
|
+
|
|
42
54
|
static VALUE integration_run_qagp(VALUE data) {
|
|
43
55
|
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
44
56
|
size_t index;
|
|
57
|
+
|
|
45
58
|
params->points = ALLOC_N(double, params->point_count);
|
|
59
|
+
|
|
46
60
|
for (index = 0; index < params->point_count; index++) {
|
|
47
61
|
params->points[index] =
|
|
48
62
|
NUM2DBL(rb_ary_entry(params->points_array, (long)index));
|
|
49
63
|
}
|
|
64
|
+
|
|
50
65
|
params->workspace = gsl_integration_workspace_alloc(params->limit);
|
|
66
|
+
|
|
51
67
|
(void)gsl_integration_qagp(params->function, params->points,
|
|
52
68
|
params->point_count, params->epsabs,
|
|
53
69
|
params->epsrel, params->limit, params->workspace,
|
|
54
70
|
params->result, params->error);
|
|
71
|
+
|
|
55
72
|
return Qnil;
|
|
56
73
|
}
|
|
74
|
+
|
|
57
75
|
static VALUE integration_free_qagp_resources(VALUE data) {
|
|
58
76
|
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
77
|
+
|
|
59
78
|
if (params->workspace != NULL) {
|
|
60
79
|
gsl_integration_workspace_free(params->workspace);
|
|
61
80
|
}
|
|
81
|
+
|
|
62
82
|
if (params->points != NULL) {
|
|
63
83
|
xfree(params->points);
|
|
64
84
|
}
|
|
85
|
+
|
|
65
86
|
return Qnil;
|
|
66
87
|
}
|
|
88
|
+
|
|
67
89
|
static VALUE integration_run_qagp_with_resources(VALUE data) {
|
|
68
90
|
return rb_ensure(integration_run_qagp, data, integration_free_qagp_resources,
|
|
69
91
|
data);
|
|
70
92
|
}
|
|
93
|
+
|
|
71
94
|
VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
72
95
|
VALUE points;
|
|
73
96
|
VALUE options;
|
|
@@ -81,14 +104,21 @@ VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
|
81
104
|
double result;
|
|
82
105
|
double error;
|
|
83
106
|
int state = 0;
|
|
107
|
+
|
|
84
108
|
(void)self;
|
|
109
|
+
|
|
85
110
|
rb_scan_args(argc, argv, "1:", &points, &options);
|
|
111
|
+
|
|
86
112
|
integration_validate_qagp_points(points);
|
|
113
|
+
|
|
87
114
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
115
|
+
|
|
88
116
|
epsabs = parsed_options.epsabs;
|
|
89
117
|
epsrel = parsed_options.epsrel;
|
|
90
118
|
limit = parsed_options.limit;
|
|
119
|
+
|
|
91
120
|
integration_function_init(&function, ¶ms);
|
|
121
|
+
|
|
92
122
|
qagp_params.points_array = points;
|
|
93
123
|
qagp_params.function = &function;
|
|
94
124
|
qagp_params.points = NULL;
|
|
@@ -99,10 +129,14 @@ VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
|
99
129
|
qagp_params.workspace = NULL;
|
|
100
130
|
qagp_params.result = &result;
|
|
101
131
|
qagp_params.error = &error;
|
|
132
|
+
|
|
102
133
|
rb_protect(integration_run_qagp_with_resources, (VALUE)&qagp_params, &state);
|
|
134
|
+
|
|
103
135
|
RB_GC_GUARD(points);
|
|
104
136
|
RB_GC_GUARD(params.block);
|
|
105
137
|
RB_GC_GUARD(params.exception);
|
|
138
|
+
|
|
106
139
|
integration_finish_callback(¶ms, state);
|
|
140
|
+
|
|
107
141
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
108
142
|
}
|
|
@@ -50,6 +50,7 @@ VALUE integration_qags(int argc, VALUE *argv, VALUE self) {
|
|
|
50
50
|
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
51
51
|
|
|
52
52
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
53
|
+
|
|
53
54
|
epsabs = parsed_options.epsabs;
|
|
54
55
|
epsrel = parsed_options.epsrel;
|
|
55
56
|
limit = parsed_options.limit;
|
|
@@ -15,14 +15,17 @@ typedef struct {
|
|
|
15
15
|
|
|
16
16
|
static VALUE integration_run_qawc(VALUE data) {
|
|
17
17
|
integration_qawc_params *params = (integration_qawc_params *)data;
|
|
18
|
+
|
|
18
19
|
(void)gsl_integration_qawc(params->function, params->a, params->b, params->c,
|
|
19
20
|
params->epsabs, params->epsrel, params->limit,
|
|
20
21
|
params->workspace, params->result, params->error);
|
|
22
|
+
|
|
21
23
|
return Qnil;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
static VALUE integration_run_qawc_with_workspace(VALUE data) {
|
|
25
27
|
integration_qawc_params *params = (integration_qawc_params *)data;
|
|
28
|
+
|
|
26
29
|
return rb_ensure(integration_run_qawc, data, integration_free_workspace,
|
|
27
30
|
(VALUE)params->workspace);
|
|
28
31
|
}
|
|
@@ -43,11 +46,13 @@ VALUE integration_qawc(int argc, VALUE *argv, VALUE self) {
|
|
|
43
46
|
double result;
|
|
44
47
|
double error;
|
|
45
48
|
int state = 0;
|
|
49
|
+
|
|
46
50
|
(void)self;
|
|
47
51
|
|
|
48
52
|
rb_scan_args(argc, argv, "3:", &a, &b, &c, &options);
|
|
49
53
|
|
|
50
54
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
55
|
+
|
|
51
56
|
epsabs = parsed_options.epsabs;
|
|
52
57
|
epsrel = parsed_options.epsrel;
|
|
53
58
|
limit = parsed_options.limit;
|
|
@@ -55,6 +60,7 @@ VALUE integration_qawc(int argc, VALUE *argv, VALUE self) {
|
|
|
55
60
|
integration_function_init(&function, ¶ms);
|
|
56
61
|
|
|
57
62
|
workspace = gsl_integration_workspace_alloc(limit);
|
|
63
|
+
|
|
58
64
|
qawc_params.function = &function;
|
|
59
65
|
qawc_params.a = NUM2DBL(a);
|
|
60
66
|
qawc_params.b = NUM2DBL(b);
|
|
@@ -67,8 +73,10 @@ VALUE integration_qawc(int argc, VALUE *argv, VALUE self) {
|
|
|
67
73
|
qawc_params.error = &error;
|
|
68
74
|
|
|
69
75
|
rb_protect(integration_run_qawc_with_workspace, (VALUE)&qawc_params, &state);
|
|
76
|
+
|
|
70
77
|
RB_GC_GUARD(params.block);
|
|
71
78
|
RB_GC_GUARD(params.exception);
|
|
79
|
+
|
|
72
80
|
integration_finish_callback(¶ms, state);
|
|
73
81
|
|
|
74
82
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
@@ -4,6 +4,7 @@ typedef struct {
|
|
|
4
4
|
gsl_function *function;
|
|
5
5
|
double a;
|
|
6
6
|
double omega;
|
|
7
|
+
|
|
7
8
|
enum gsl_integration_qawo_enum sine;
|
|
8
9
|
double epsabs;
|
|
9
10
|
size_t limit;
|
|
@@ -20,9 +21,11 @@ static VALUE integration_free_qawf_resources(VALUE data) {
|
|
|
20
21
|
if (params->table != NULL) {
|
|
21
22
|
gsl_integration_qawo_table_free(params->table);
|
|
22
23
|
}
|
|
24
|
+
|
|
23
25
|
if (params->cycle_workspace != NULL) {
|
|
24
26
|
gsl_integration_workspace_free(params->cycle_workspace);
|
|
25
27
|
}
|
|
28
|
+
|
|
26
29
|
if (params->workspace != NULL) {
|
|
27
30
|
gsl_integration_workspace_free(params->workspace);
|
|
28
31
|
}
|
|
@@ -5,6 +5,7 @@ typedef struct {
|
|
|
5
5
|
double a;
|
|
6
6
|
double b;
|
|
7
7
|
double omega;
|
|
8
|
+
|
|
8
9
|
enum gsl_integration_qawo_enum sine;
|
|
9
10
|
double epsabs;
|
|
10
11
|
double epsrel;
|
|
@@ -21,6 +22,7 @@ static VALUE integration_free_qawo_resources(VALUE data) {
|
|
|
21
22
|
if (params->table != NULL) {
|
|
22
23
|
gsl_integration_qawo_table_free(params->table);
|
|
23
24
|
}
|
|
25
|
+
|
|
24
26
|
if (params->workspace != NULL) {
|
|
25
27
|
gsl_integration_workspace_free(params->workspace);
|
|
26
28
|
}
|
|
@@ -69,6 +71,7 @@ VALUE integration_qawo(int argc, VALUE *argv, VALUE self) {
|
|
|
69
71
|
rb_scan_args(argc, argv, "4:", &a, &b, &omega, &sine, &options);
|
|
70
72
|
|
|
71
73
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
74
|
+
|
|
72
75
|
epsabs = parsed_options.epsabs;
|
|
73
76
|
epsrel = parsed_options.epsrel;
|
|
74
77
|
limit = parsed_options.limit;
|
|
@@ -23,6 +23,7 @@ static VALUE integration_free_qaws_resources(VALUE data) {
|
|
|
23
23
|
if (params->table != NULL) {
|
|
24
24
|
gsl_integration_qaws_table_free(params->table);
|
|
25
25
|
}
|
|
26
|
+
|
|
26
27
|
if (params->workspace != NULL) {
|
|
27
28
|
gsl_integration_workspace_free(params->workspace);
|
|
28
29
|
}
|
|
@@ -36,6 +37,7 @@ static VALUE integration_run_qaws(VALUE data) {
|
|
|
36
37
|
params->table = gsl_integration_qaws_table_alloc(params->alpha, params->beta,
|
|
37
38
|
params->mu, params->nu);
|
|
38
39
|
params->workspace = gsl_integration_workspace_alloc(params->limit);
|
|
40
|
+
|
|
39
41
|
(void)gsl_integration_qaws(params->function, params->a, params->b,
|
|
40
42
|
params->table, params->epsabs, params->epsrel,
|
|
41
43
|
params->limit, params->workspace, params->result,
|
|
@@ -69,9 +71,11 @@ VALUE integration_qaws(int argc, VALUE *argv, VALUE self) {
|
|
|
69
71
|
int state = 0;
|
|
70
72
|
|
|
71
73
|
(void)self;
|
|
74
|
+
|
|
72
75
|
rb_scan_args(argc, argv, "6:", &a, &b, &alpha, &beta, &mu, &nu, &options);
|
|
73
76
|
|
|
74
77
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
78
|
+
|
|
75
79
|
epsabs = parsed_options.epsabs;
|
|
76
80
|
epsrel = parsed_options.epsrel;
|
|
77
81
|
limit = parsed_options.limit;
|
|
@@ -94,8 +98,10 @@ VALUE integration_qaws(int argc, VALUE *argv, VALUE self) {
|
|
|
94
98
|
qaws_params.error = &error;
|
|
95
99
|
|
|
96
100
|
rb_protect(integration_run_qaws_with_resources, (VALUE)&qaws_params, &state);
|
|
101
|
+
|
|
97
102
|
RB_GC_GUARD(params.block);
|
|
98
103
|
RB_GC_GUARD(params.exception);
|
|
104
|
+
|
|
99
105
|
integration_finish_callback(¶ms, state);
|
|
100
106
|
|
|
101
107
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
@@ -50,6 +50,7 @@ VALUE integration_romberg(int argc, VALUE *argv, VALUE self) {
|
|
|
50
50
|
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
51
51
|
|
|
52
52
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 20);
|
|
53
|
+
|
|
53
54
|
epsabs = parsed_options.epsabs;
|
|
54
55
|
epsrel = parsed_options.epsrel;
|
|
55
56
|
limit = parsed_options.limit;
|
|
@@ -108,6 +108,14 @@ module Numo
|
|
|
108
108
|
Numeric b,
|
|
109
109
|
?order: Integer
|
|
110
110
|
) { (Float) -> Numeric } -> Float
|
|
111
|
+
def self.fixed: (
|
|
112
|
+
(:legendre | :chebyshev | :chebyshev2 | :gegenbauer | :jacobi | :laguerre | :hermite | :exponential | :rational) type,
|
|
113
|
+
order: Integer,
|
|
114
|
+
a: Numeric,
|
|
115
|
+
b: Numeric,
|
|
116
|
+
?alpha: Numeric,
|
|
117
|
+
?beta: Numeric
|
|
118
|
+
) { (Float) -> Numeric } -> Float
|
|
111
119
|
end
|
|
112
120
|
end
|
|
113
121
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: numo-gsl-integration
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Takahiro SATOH
|
|
@@ -27,6 +27,7 @@ files:
|
|
|
27
27
|
- ext/numo/gsl/integration/callback.c
|
|
28
28
|
- ext/numo/gsl/integration/cquad.c
|
|
29
29
|
- ext/numo/gsl/integration/extconf.rb
|
|
30
|
+
- ext/numo/gsl/integration/fixed.c
|
|
30
31
|
- ext/numo/gsl/integration/glfixed.c
|
|
31
32
|
- ext/numo/gsl/integration/integration.c
|
|
32
33
|
- ext/numo/gsl/integration/integration_internal.h
|