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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01ba50fbaebaceaa6e5d4151c60a5cda604fbdb45cb78fe0cdbce009916d0028
4
- data.tar.gz: 50080c206cf316e836e6e36c7a33492665a1eaa6a832704d98046aa090c2d70b
3
+ metadata.gz: 24601b3a87462ee4bc6077999599478d3c08776b8da2caa648e56dbfaacec731
4
+ data.tar.gz: 97d7fe3772e374a35ab108ea0a4238fbbceb04598fc2637c3f4d76285cc17f66
5
5
  SHA512:
6
- metadata.gz: 52e2c27c1aa5bec02da2afb0c737eb607f8517f2c4ce55d2fdf26ce8ab72c5003d3ce79ff755b8430bae7479864ea90ad7b1340454e99b9b133cd0223be943df
7
- data.tar.gz: 45e2d49aaa8c374e8e4591965d71dc91468fa855bd73779363ab71dbf997e1484a0ff2bb33e4925ecfa2b05c5d90533d943ea97f89efd25bb733b982d631f4e4
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–Legendre integration for smooth functions.
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 | 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 |
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–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.
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–Legendre points and defaults to `10`. It must be a positive integer.
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, &params->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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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(&params, 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;
@@ -3,7 +3,7 @@
3
3
  module Numo
4
4
  module GSL
5
5
  module Integration
6
- VERSION = "0.2.0"
6
+ VERSION = "0.3.1"
7
7
  end
8
8
  end
9
9
  end
@@ -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.2.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