numo-gsl-integration 0.2.0 → 0.3.0

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: 0ed1ccbd179314a5925c135faa809ff255bb9acf626c475af39237c8e397f89a
4
+ data.tar.gz: 891a0e74db19f6d5c5b40aeff66a2610dbf063c5d2ccd3b9dfdae0a730a880fd
5
5
  SHA512:
6
- metadata.gz: 52e2c27c1aa5bec02da2afb0c737eb607f8517f2c4ce55d2fdf26ce8ab72c5003d3ce79ff755b8430bae7479864ea90ad7b1340454e99b9b133cd0223be943df
7
- data.tar.gz: 45e2d49aaa8c374e8e4591965d71dc91468fa855bd73779363ab71dbf997e1484a0ff2bb33e4925ecfa2b05c5d90533d943ea97f89efd25bb733b982d631f4e4
6
+ metadata.gz: 86207b0346bcff38a8892e36c8721d2327010b7367a74b91344db9c799ae2ea0390203572ce275efad201a47bc480f66e26b1daad753cfd63c878c7b78575793
7
+ data.tar.gz: 532c33c4e35c701e901cf10d771a9c982533b927353dbbe0d53173684dc2ab66a90231e617906a10cc3d530aa05f364ea83735982e3721b421e06e1cbb2b983a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.3.0] - 2026-11-05
6
+
7
+ ### Added in 0.3.0
8
+
9
+ - Added fixed point quadrature with Legendre, first- and second-kind Chebyshev, Gegenbauer, Jacobi, Laguerre, Hermite, exponential, and rational rules.
10
+
5
11
  ## [0.2.0] - 2026-11-05
6
12
 
7
13
  ### Changed in 0.2.0
@@ -22,7 +28,7 @@
22
28
 
23
29
  ### Added in 0.1.0
24
30
 
25
- - Added fixed-order Gauss–Legendre integration for smooth functions.
31
+ - Added fixed-order Gauss-Legendre integration for smooth functions.
26
32
  - Added Romberg integration for smooth functions with function-evaluation counts.
27
33
  - Added CQUAD doubly-adaptive integration with function-evaluation counts.
28
34
  - 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,17 @@ 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
184
+ PV \\int_a^b \\frac{f(x)}{x-c}\\,dx
185
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)
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)
192
192
  ```
193
193
 
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.
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.
195
195
  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
196
 
197
197
  ```ruby
@@ -220,15 +220,15 @@ end
220
220
  GSL [QAWS](https://www.gnu.org/software/gsl/doc/html/integration.html#qaws-adaptive-integration-for-singular-functions) provides adaptive integration for functions with algebraic or logarithmic singularities at the endpoints of a finite interval. It computes an integral with the weight
221
221
 
222
222
  ```math
223
- (x-a)^\alpha (b-x)^\beta
224
- \log^\mu(x-a) \log^\nu(b-x).
223
+ (x-a)^\\alpha (b-x)^\\beta
224
+ \\log^\\mu(x-a) \\log^\\nu(b-x).
225
225
  ```
226
226
 
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`.
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`.
228
228
  The block returns the unweighted function $f(x)$. QAWS applies the endpoint weight internally. The following example integrates
229
229
 
230
230
  ```math
231
- \frac{1}{\sqrt{x(1-x)}}
231
+ \\frac{1}{\\sqrt{x(1-x)}}
232
232
  ```
233
233
 
234
234
  over the interval from `0.0` to `1.0`. Its exact value is `Math::PI`:
@@ -321,12 +321,12 @@ result, evaluations = Numo::GSL::Integration.romberg(0.0, Math::PI) do |x|
321
321
  end
322
322
  ```
323
323
 
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.
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.
325
325
  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
326
 
327
327
  ## GLFIXED integration
328
328
 
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.
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.
330
330
 
331
331
  ```ruby
332
332
  result = Numo::GSL::Integration.glfixed(
@@ -338,5 +338,55 @@ result = Numo::GSL::Integration.glfixed(
338
338
  end
339
339
  ```
340
340
 
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.
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.
342
342
  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.
343
+
344
+ ## Fixed point quadratures
345
+
346
+ 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:
347
+
348
+ ```ruby
349
+ result = Numo::GSL::Integration.fixed(
350
+ :legendre,
351
+ order: 3,
352
+ a: 0.0,
353
+ b: 1.0
354
+ ) do |x|
355
+ x ** 4
356
+ end
357
+ ```
358
+
359
+ 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.
360
+
361
+ The supported types and required keyword arguments are:
362
+
363
+ | Type | Required rule parameters | Description |
364
+ | -------------- | ------------------------ | ------------------------------------------------------------ |
365
+ | `:legendre` | — | Gauss-Legendre rule over the finite interval from `a` to `b` |
366
+ | `:chebyshev` | — | First-kind Chebyshev rule over the finite interval |
367
+ | `:chebyshev2` | — | Second-kind Chebyshev rule over the finite interval |
368
+ | `:gegenbauer` | `alpha` | Gegenbauer rule |
369
+ | `:jacobi` | `alpha`, `beta` | Jacobi rule |
370
+ | `:laguerre` | `alpha` | Generalized Laguerre rule |
371
+ | `:hermite` | `alpha` | Generalized Hermite rule |
372
+ | `:exponential` | `alpha` | Exponential rule over a finite interval |
373
+ | `:rational` | `alpha`, `beta` | Rational rule |
374
+
375
+ `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.
376
+
377
+ The following example uses the rational rule. Its parameters satisfy the rule's order-dependent constraints for `order: 3`:
378
+
379
+ ```ruby
380
+ result = Numo::GSL::Integration.fixed(
381
+ :rational,
382
+ order: 3,
383
+ a: 0.0,
384
+ b: 1.0,
385
+ alpha: 0.0,
386
+ beta: -7.0
387
+ ) do |_x|
388
+ 1.0
389
+ end
390
+ ```
391
+
392
+ 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,163 @@
1
+ #include "integration_internal.h"
2
+ typedef struct {
3
+ gsl_function *function;
4
+ const gsl_integration_fixed_type *type;
5
+ size_t order;
6
+ double a;
7
+ double b;
8
+ double alpha;
9
+ double beta;
10
+ gsl_integration_fixed_workspace *workspace;
11
+ double *result;
12
+ } integration_fixed_params;
13
+ static const gsl_integration_fixed_type *integration_fixed_type(VALUE type) {
14
+ ID type_id;
15
+ if (!RB_TYPE_P(type, T_SYMBOL)) {
16
+ rb_raise(rb_eTypeError, "type must be a Symbol");
17
+ }
18
+ type_id = SYM2ID(type);
19
+ if (type_id == rb_intern("legendre")) {
20
+ return gsl_integration_fixed_legendre;
21
+ }
22
+ if (type_id == rb_intern("chebyshev")) {
23
+ return gsl_integration_fixed_chebyshev;
24
+ }
25
+ if (type_id == rb_intern("chebyshev2")) {
26
+ return gsl_integration_fixed_chebyshev2;
27
+ }
28
+ if (type_id == rb_intern("gegenbauer")) {
29
+ return gsl_integration_fixed_gegenbauer;
30
+ }
31
+ if (type_id == rb_intern("jacobi")) {
32
+ return gsl_integration_fixed_jacobi;
33
+ }
34
+ if (type_id == rb_intern("laguerre")) {
35
+ return gsl_integration_fixed_laguerre;
36
+ }
37
+ if (type_id == rb_intern("hermite")) {
38
+ return gsl_integration_fixed_hermite;
39
+ }
40
+ if (type_id == rb_intern("exponential")) {
41
+ return gsl_integration_fixed_exponential;
42
+ }
43
+ if (type_id == rb_intern("rational")) {
44
+ return gsl_integration_fixed_rational;
45
+ }
46
+ rb_raise(rb_eArgError, "unsupported fixed quadrature type: %s",
47
+ rb_id2name(type_id));
48
+ }
49
+ static VALUE integration_free_fixed_workspace(VALUE data) {
50
+ integration_fixed_params *params = (integration_fixed_params *)data;
51
+ if (params->workspace != NULL) {
52
+ gsl_integration_fixed_free(params->workspace);
53
+ }
54
+ return Qnil;
55
+ }
56
+ static VALUE integration_run_fixed(VALUE data) {
57
+ integration_fixed_params *params = (integration_fixed_params *)data;
58
+ params->workspace =
59
+ gsl_integration_fixed_alloc(params->type, params->order, params->a,
60
+ params->b, params->alpha, params->beta);
61
+ if (params->workspace == NULL) {
62
+ rb_memerror();
63
+ }
64
+ (void)gsl_integration_fixed(params->function, params->result,
65
+ params->workspace);
66
+ return Qnil;
67
+ }
68
+ static VALUE integration_run_fixed_with_workspace(VALUE data) {
69
+ return rb_ensure(integration_run_fixed, data,
70
+ integration_free_fixed_workspace, data);
71
+ }
72
+ VALUE integration_fixed(int argc, VALUE *argv, VALUE self) {
73
+ VALUE type;
74
+ VALUE options;
75
+ ID keywords[] = {rb_intern("order"), rb_intern("a"), rb_intern("b"),
76
+ rb_intern("alpha"), rb_intern("beta")};
77
+ VALUE keyword_values[5];
78
+ VALUE order_value;
79
+ VALUE alpha_value;
80
+ VALUE beta_value;
81
+ size_t order;
82
+ gsl_function function;
83
+ integration_callback_params params;
84
+ integration_fixed_params fixed_params;
85
+ double result;
86
+ int state = 0;
87
+ (void)self;
88
+ rb_scan_args(argc, argv, "1:", &type, &options);
89
+ fixed_params.type = integration_fixed_type(type);
90
+ if (NIL_P(options)) {
91
+ options = rb_hash_new();
92
+ }
93
+ rb_get_kwargs(options, keywords, 3, 2, keyword_values);
94
+ order_value = keyword_values[0];
95
+ alpha_value = keyword_values[3];
96
+ beta_value = keyword_values[4];
97
+ if (!RB_INTEGER_TYPE_P(order_value)) {
98
+ rb_raise(rb_eTypeError, "order must be an Integer");
99
+ }
100
+ if (RTEST(rb_funcall(order_value, rb_intern("<="), 1, INT2FIX(0)))) {
101
+ rb_raise(rb_eArgError, "order must be positive");
102
+ }
103
+ order = NUM2SIZET(order_value);
104
+ integration_function_init(&function, &params);
105
+ fixed_params.function = &function;
106
+ fixed_params.order = order;
107
+ fixed_params.a = NUM2DBL(keyword_values[1]);
108
+ fixed_params.b = NUM2DBL(keyword_values[2]);
109
+ if (fixed_params.type == gsl_integration_fixed_gegenbauer) {
110
+ if (alpha_value == Qundef) {
111
+ rb_raise(rb_eArgError, "alpha is required for gegenbauer");
112
+ }
113
+ fixed_params.alpha = NUM2DBL(alpha_value);
114
+ fixed_params.beta = 0.0;
115
+ } else if (fixed_params.type == gsl_integration_fixed_jacobi) {
116
+ if (alpha_value == Qundef) {
117
+ rb_raise(rb_eArgError, "alpha is required for jacobi");
118
+ }
119
+ if (beta_value == Qundef) {
120
+ rb_raise(rb_eArgError, "beta is required for jacobi");
121
+ }
122
+ fixed_params.alpha = NUM2DBL(alpha_value);
123
+ fixed_params.beta = NUM2DBL(beta_value);
124
+ } else if (fixed_params.type == gsl_integration_fixed_laguerre) {
125
+ if (alpha_value == Qundef) {
126
+ rb_raise(rb_eArgError, "alpha is required for laguerre");
127
+ }
128
+ fixed_params.alpha = NUM2DBL(alpha_value);
129
+ fixed_params.beta = 0.0;
130
+ } else if (fixed_params.type == gsl_integration_fixed_hermite) {
131
+ if (alpha_value == Qundef) {
132
+ rb_raise(rb_eArgError, "alpha is required for hermite");
133
+ }
134
+ fixed_params.alpha = NUM2DBL(alpha_value);
135
+ fixed_params.beta = 0.0;
136
+ } else if (fixed_params.type == gsl_integration_fixed_exponential) {
137
+ if (alpha_value == Qundef) {
138
+ rb_raise(rb_eArgError, "alpha is required for exponential");
139
+ }
140
+ fixed_params.alpha = NUM2DBL(alpha_value);
141
+ fixed_params.beta = 0.0;
142
+ } else if (fixed_params.type == gsl_integration_fixed_rational) {
143
+ if (alpha_value == Qundef) {
144
+ rb_raise(rb_eArgError, "alpha is required for rational");
145
+ }
146
+ if (beta_value == Qundef) {
147
+ rb_raise(rb_eArgError, "beta is required for rational");
148
+ }
149
+ fixed_params.alpha = NUM2DBL(alpha_value);
150
+ fixed_params.beta = NUM2DBL(beta_value);
151
+ } else {
152
+ fixed_params.alpha = 0.0;
153
+ fixed_params.beta = 0.0;
154
+ }
155
+ fixed_params.workspace = NULL;
156
+ fixed_params.result = &result;
157
+ rb_protect(integration_run_fixed_with_workspace, (VALUE)&fixed_params,
158
+ &state);
159
+ RB_GC_GUARD(params.block);
160
+ RB_GC_GUARD(params.exception);
161
+ integration_finish_callback(&params, state);
162
+ return DBL2NUM(result);
163
+ }
@@ -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,25 @@
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
+
18
23
  rb_define_const(mIntegration, "GAUSS15", INT2NUM(GSL_INTEG_GAUSS15));
19
24
  rb_define_const(mIntegration, "GAUSS21", INT2NUM(GSL_INTEG_GAUSS21));
20
25
  rb_define_const(mIntegration, "GAUSS31", INT2NUM(GSL_INTEG_GAUSS31));
@@ -23,6 +28,7 @@ void Init_integration(void) {
23
28
  rb_define_const(mIntegration, "GAUSS61", INT2NUM(GSL_INTEG_GAUSS61));
24
29
  rb_define_const(mIntegration, "COSINE", INT2NUM(GSL_INTEG_COSINE));
25
30
  rb_define_const(mIntegration, "SINE", INT2NUM(GSL_INTEG_SINE));
31
+
26
32
  rb_define_singleton_method(mIntegration, "qag", integration_qag, -1);
27
33
  rb_define_singleton_method(mIntegration, "qng", integration_qng, -1);
28
34
  rb_define_singleton_method(mIntegration, "qags", integration_qags, -1);
@@ -37,4 +43,5 @@ void Init_integration(void) {
37
43
  rb_define_singleton_method(mIntegration, "cquad", integration_cquad, -1);
38
44
  rb_define_singleton_method(mIntegration, "romberg", integration_romberg, -1);
39
45
  rb_define_singleton_method(mIntegration, "glfixed", integration_glfixed, -1);
46
+ rb_define_singleton_method(mIntegration, "fixed", integration_fixed, -1);
40
47
  }
@@ -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,12 @@ 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
+
31
38
  VALUE integration_qag(int argc, VALUE *argv, VALUE self);
32
39
  VALUE integration_qng(int argc, VALUE *argv, VALUE self);
33
40
  VALUE integration_qags(int argc, VALUE *argv, VALUE self);
@@ -42,4 +49,6 @@ VALUE integration_qawf(int argc, VALUE *argv, VALUE self);
42
49
  VALUE integration_cquad(int argc, VALUE *argv, VALUE self);
43
50
  VALUE integration_romberg(int argc, VALUE *argv, VALUE self);
44
51
  VALUE integration_glfixed(int argc, VALUE *argv, VALUE self);
52
+ VALUE integration_fixed(int argc, VALUE *argv, VALUE self);
53
+
45
54
  #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.0"
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.0
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