numo-gsl-integration 0.3.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 +6 -0
- data/docs/routines.md +4 -11
- data/ext/numo/gsl/integration/fixed.c +106 -79
- data/ext/numo/gsl/integration/integration.c +1 -0
- data/ext/numo/gsl/integration/integration_internal.h +2 -0
- data/lib/numo/gsl/integration/version.rb +1 -1
- metadata +1 -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
data/docs/routines.md
CHANGED
|
@@ -181,14 +181,7 @@ 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
|
|
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
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.
|
|
@@ -220,15 +213,15 @@ end
|
|
|
220
213
|
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
214
|
|
|
222
215
|
```math
|
|
223
|
-
(x-a)
|
|
224
|
-
|
|
216
|
+
(x-a)^\alpha (b-x)^\beta
|
|
217
|
+
\log^\mu(x-a) \log^\nu(b-x).
|
|
225
218
|
```
|
|
226
219
|
|
|
227
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
|
|
231
|
-
|
|
224
|
+
\frac{1}{\sqrt{x(1-x)}}
|
|
232
225
|
```
|
|
233
226
|
|
|
234
227
|
over the interval from `0.0` to `1.0`. Its exact value is `Math::PI`:
|
|
@@ -1,4 +1,17 @@
|
|
|
1
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
|
+
|
|
2
15
|
typedef struct {
|
|
3
16
|
gsl_function *function;
|
|
4
17
|
const gsl_integration_fixed_type *type;
|
|
@@ -10,150 +23,164 @@ typedef struct {
|
|
|
10
23
|
gsl_integration_fixed_workspace *workspace;
|
|
11
24
|
double *result;
|
|
12
25
|
} integration_fixed_params;
|
|
13
|
-
|
|
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) {
|
|
14
70
|
ID type_id;
|
|
71
|
+
size_t i;
|
|
72
|
+
|
|
15
73
|
if (!RB_TYPE_P(type, T_SYMBOL)) {
|
|
16
74
|
rb_raise(rb_eTypeError, "type must be a Symbol");
|
|
17
75
|
}
|
|
76
|
+
|
|
18
77
|
type_id = SYM2ID(type);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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;
|
|
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
|
+
}
|
|
45
84
|
}
|
|
85
|
+
|
|
46
86
|
rb_raise(rb_eArgError, "unsupported fixed quadrature type: %s",
|
|
47
87
|
rb_id2name(type_id));
|
|
48
88
|
}
|
|
89
|
+
|
|
49
90
|
static VALUE integration_free_fixed_workspace(VALUE data) {
|
|
50
91
|
integration_fixed_params *params = (integration_fixed_params *)data;
|
|
92
|
+
|
|
51
93
|
if (params->workspace != NULL) {
|
|
52
94
|
gsl_integration_fixed_free(params->workspace);
|
|
53
95
|
}
|
|
54
96
|
return Qnil;
|
|
55
97
|
}
|
|
98
|
+
|
|
56
99
|
static VALUE integration_run_fixed(VALUE data) {
|
|
57
100
|
integration_fixed_params *params = (integration_fixed_params *)data;
|
|
101
|
+
|
|
58
102
|
params->workspace =
|
|
59
103
|
gsl_integration_fixed_alloc(params->type, params->order, params->a,
|
|
60
104
|
params->b, params->alpha, params->beta);
|
|
61
105
|
if (params->workspace == NULL) {
|
|
62
106
|
rb_memerror();
|
|
63
107
|
}
|
|
108
|
+
|
|
64
109
|
(void)gsl_integration_fixed(params->function, params->result,
|
|
65
110
|
params->workspace);
|
|
66
111
|
return Qnil;
|
|
67
112
|
}
|
|
113
|
+
|
|
68
114
|
static VALUE integration_run_fixed_with_workspace(VALUE data) {
|
|
69
115
|
return rb_ensure(integration_run_fixed, data,
|
|
70
116
|
integration_free_fixed_workspace, data);
|
|
71
117
|
}
|
|
118
|
+
|
|
72
119
|
VALUE integration_fixed(int argc, VALUE *argv, VALUE self) {
|
|
73
120
|
VALUE type;
|
|
74
121
|
VALUE options;
|
|
75
|
-
ID keywords[] = {
|
|
76
|
-
|
|
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};
|
|
77
125
|
VALUE keyword_values[5];
|
|
78
126
|
VALUE order_value;
|
|
79
127
|
VALUE alpha_value;
|
|
80
128
|
VALUE beta_value;
|
|
129
|
+
const integration_fixed_type_info *type_info;
|
|
81
130
|
size_t order;
|
|
82
131
|
gsl_function function;
|
|
83
132
|
integration_callback_params params;
|
|
84
|
-
integration_fixed_params fixed_params;
|
|
133
|
+
integration_fixed_params fixed_params = {0};
|
|
85
134
|
double result;
|
|
86
135
|
int state = 0;
|
|
136
|
+
|
|
87
137
|
(void)self;
|
|
88
138
|
rb_scan_args(argc, argv, "1:", &type, &options);
|
|
89
|
-
|
|
139
|
+
type_info = integration_fixed_type(type);
|
|
140
|
+
|
|
90
141
|
if (NIL_P(options)) {
|
|
91
142
|
options = rb_hash_new();
|
|
92
143
|
}
|
|
93
144
|
rb_get_kwargs(options, keywords, 3, 2, keyword_values);
|
|
145
|
+
|
|
94
146
|
order_value = keyword_values[0];
|
|
95
147
|
alpha_value = keyword_values[3];
|
|
96
148
|
beta_value = keyword_values[4];
|
|
149
|
+
|
|
97
150
|
if (!RB_INTEGER_TYPE_P(order_value)) {
|
|
98
151
|
rb_raise(rb_eTypeError, "order must be an Integer");
|
|
99
152
|
}
|
|
100
|
-
if (RTEST(rb_funcall(order_value,
|
|
153
|
+
if (RTEST(rb_funcall(order_value, integration_fixed_id_less_than_or_equal, 1,
|
|
154
|
+
INT2FIX(0)))) {
|
|
101
155
|
rb_raise(rb_eArgError, "order must be positive");
|
|
102
156
|
}
|
|
103
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
|
+
|
|
104
168
|
integration_function_init(&function, ¶ms);
|
|
105
169
|
fixed_params.function = &function;
|
|
170
|
+
fixed_params.type = *type_info->type;
|
|
106
171
|
fixed_params.order = order;
|
|
107
172
|
fixed_params.a = NUM2DBL(keyword_values[1]);
|
|
108
173
|
fixed_params.b = NUM2DBL(keyword_values[2]);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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;
|
|
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;
|
|
156
182
|
fixed_params.result = &result;
|
|
183
|
+
|
|
157
184
|
rb_protect(integration_run_fixed_with_workspace, (VALUE)&fixed_params,
|
|
158
185
|
&state);
|
|
159
186
|
RB_GC_GUARD(params.block);
|
|
@@ -19,6 +19,7 @@ void Init_integration(void) {
|
|
|
19
19
|
mIntegration = rb_define_module_under(mGSL, "Integration");
|
|
20
20
|
numo_eGslError = rb_define_class_under(mGSL, "GslError", rb_eStandardError);
|
|
21
21
|
gsl_set_error_handler(&integration_gsl_error_handler);
|
|
22
|
+
integration_fixed_init();
|
|
22
23
|
|
|
23
24
|
rb_define_const(mIntegration, "GAUSS15", INT2NUM(GSL_INTEG_GAUSS15));
|
|
24
25
|
rb_define_const(mIntegration, "GAUSS21", INT2NUM(GSL_INTEG_GAUSS21));
|
|
@@ -35,6 +35,8 @@ VALUE integration_free_cquad_workspace(VALUE data);
|
|
|
35
35
|
VALUE integration_free_romberg_workspace(VALUE data);
|
|
36
36
|
VALUE integration_free_glfixed_table(VALUE data);
|
|
37
37
|
|
|
38
|
+
void integration_fixed_init(void);
|
|
39
|
+
|
|
38
40
|
VALUE integration_qag(int argc, VALUE *argv, VALUE self);
|
|
39
41
|
VALUE integration_qng(int argc, VALUE *argv, VALUE self);
|
|
40
42
|
VALUE integration_qags(int argc, VALUE *argv, VALUE self);
|