numo-gsl-integration 0.1.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 +7 -0
- data/CHANGELOG.md +31 -0
- data/LICENSE +674 -0
- data/README.md +80 -0
- data/docs/development.md +49 -0
- data/docs/error-handling.md +19 -0
- data/docs/routines.md +288 -0
- data/ext/numo/gsl/integration/callback.c +61 -0
- data/ext/numo/gsl/integration/cquad.c +84 -0
- data/ext/numo/gsl/integration/extconf.rb +13 -0
- data/ext/numo/gsl/integration/glfixed.c +74 -0
- data/ext/numo/gsl/integration/integration.c +35 -0
- data/ext/numo/gsl/integration/integration_internal.h +52 -0
- data/ext/numo/gsl/integration/options.c +26 -0
- data/ext/numo/gsl/integration/qag.c +90 -0
- data/ext/numo/gsl/integration/qagi.c +73 -0
- data/ext/numo/gsl/integration/qagil.c +70 -0
- data/ext/numo/gsl/integration/qagiu.c +70 -0
- data/ext/numo/gsl/integration/qagp.c +130 -0
- data/ext/numo/gsl/integration/qags.c +79 -0
- data/ext/numo/gsl/integration/qawc.c +75 -0
- data/ext/numo/gsl/integration/qawf.c +107 -0
- data/ext/numo/gsl/integration/qawo.c +99 -0
- data/ext/numo/gsl/integration/qaws.c +102 -0
- data/ext/numo/gsl/integration/qng.c +75 -0
- data/ext/numo/gsl/integration/resources.c +35 -0
- data/ext/numo/gsl/integration/romberg.c +79 -0
- data/lib/numo/gsl/integration/version.rb +9 -0
- data/lib/numo/gsl/integration.rb +15 -0
- data/sig/numo/gsl/integration.rbs +131 -0
- data/sig/numo/gsl.rbs +6 -0
- metadata +96 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
void Init_integration(void) {
|
|
4
|
+
VALUE mNumo;
|
|
5
|
+
VALUE mGSL;
|
|
6
|
+
VALUE mIntegration;
|
|
7
|
+
|
|
8
|
+
mNumo = rb_define_module("Numo");
|
|
9
|
+
mGSL = rb_define_module_under(mNumo, "GSL");
|
|
10
|
+
mIntegration = rb_define_module_under(mGSL, "Integration");
|
|
11
|
+
|
|
12
|
+
rb_define_const(mIntegration, "GAUSS15", INT2NUM(GSL_INTEG_GAUSS15));
|
|
13
|
+
rb_define_const(mIntegration, "GAUSS21", INT2NUM(GSL_INTEG_GAUSS21));
|
|
14
|
+
rb_define_const(mIntegration, "GAUSS31", INT2NUM(GSL_INTEG_GAUSS31));
|
|
15
|
+
rb_define_const(mIntegration, "GAUSS41", INT2NUM(GSL_INTEG_GAUSS41));
|
|
16
|
+
rb_define_const(mIntegration, "GAUSS51", INT2NUM(GSL_INTEG_GAUSS51));
|
|
17
|
+
rb_define_const(mIntegration, "GAUSS61", INT2NUM(GSL_INTEG_GAUSS61));
|
|
18
|
+
rb_define_const(mIntegration, "COSINE", INT2NUM(GSL_INTEG_COSINE));
|
|
19
|
+
rb_define_const(mIntegration, "SINE", INT2NUM(GSL_INTEG_SINE));
|
|
20
|
+
|
|
21
|
+
rb_define_singleton_method(mIntegration, "qag", integration_qag, -1);
|
|
22
|
+
rb_define_singleton_method(mIntegration, "qng", integration_qng, -1);
|
|
23
|
+
rb_define_singleton_method(mIntegration, "qags", integration_qags, -1);
|
|
24
|
+
rb_define_singleton_method(mIntegration, "qagp", integration_qagp, -1);
|
|
25
|
+
rb_define_singleton_method(mIntegration, "qagi", integration_qagi, -1);
|
|
26
|
+
rb_define_singleton_method(mIntegration, "qagiu", integration_qagiu, -1);
|
|
27
|
+
rb_define_singleton_method(mIntegration, "qagil", integration_qagil, -1);
|
|
28
|
+
rb_define_singleton_method(mIntegration, "qawc", integration_qawc, -1);
|
|
29
|
+
rb_define_singleton_method(mIntegration, "qaws", integration_qaws, -1);
|
|
30
|
+
rb_define_singleton_method(mIntegration, "qawo", integration_qawo, -1);
|
|
31
|
+
rb_define_singleton_method(mIntegration, "qawf", integration_qawf, -1);
|
|
32
|
+
rb_define_singleton_method(mIntegration, "cquad", integration_cquad, -1);
|
|
33
|
+
rb_define_singleton_method(mIntegration, "romberg", integration_romberg, -1);
|
|
34
|
+
rb_define_singleton_method(mIntegration, "glfixed", integration_glfixed, -1);
|
|
35
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#ifndef NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
2
|
+
#define NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
3
|
+
|
|
4
|
+
#include <gsl/gsl_integration.h>
|
|
5
|
+
#include <ruby.h>
|
|
6
|
+
|
|
7
|
+
typedef struct {
|
|
8
|
+
double epsabs;
|
|
9
|
+
double epsrel;
|
|
10
|
+
size_t limit;
|
|
11
|
+
} integration_options;
|
|
12
|
+
|
|
13
|
+
void integration_options_parse(VALUE options, integration_options *parsed,
|
|
14
|
+
double default_epsabs, double default_epsrel,
|
|
15
|
+
size_t default_limit);
|
|
16
|
+
|
|
17
|
+
typedef struct {
|
|
18
|
+
VALUE block;
|
|
19
|
+
VALUE x;
|
|
20
|
+
VALUE exception;
|
|
21
|
+
int state;
|
|
22
|
+
} integration_callback_params;
|
|
23
|
+
|
|
24
|
+
void integration_callback_params_init(integration_callback_params *params);
|
|
25
|
+
void integration_function_init(gsl_function *function,
|
|
26
|
+
integration_callback_params *params);
|
|
27
|
+
double integration_callback(double x, void *data);
|
|
28
|
+
void integration_raise_callback_exception(integration_callback_params *params);
|
|
29
|
+
void integration_finish_callback(integration_callback_params *params,
|
|
30
|
+
int state);
|
|
31
|
+
VALUE integration_error_class(void);
|
|
32
|
+
VALUE integration_free_workspace(VALUE data);
|
|
33
|
+
VALUE integration_free_cquad_workspace(VALUE data);
|
|
34
|
+
VALUE integration_free_romberg_workspace(VALUE data);
|
|
35
|
+
VALUE integration_free_glfixed_table(VALUE data);
|
|
36
|
+
|
|
37
|
+
VALUE integration_qag(int argc, VALUE *argv, VALUE self);
|
|
38
|
+
VALUE integration_qng(int argc, VALUE *argv, VALUE self);
|
|
39
|
+
VALUE integration_qags(int argc, VALUE *argv, VALUE self);
|
|
40
|
+
VALUE integration_qagp(int argc, VALUE *argv, VALUE self);
|
|
41
|
+
VALUE integration_qagi(int argc, VALUE *argv, VALUE self);
|
|
42
|
+
VALUE integration_qagiu(int argc, VALUE *argv, VALUE self);
|
|
43
|
+
VALUE integration_qagil(int argc, VALUE *argv, VALUE self);
|
|
44
|
+
VALUE integration_qawc(int argc, VALUE *argv, VALUE self);
|
|
45
|
+
VALUE integration_qaws(int argc, VALUE *argv, VALUE self);
|
|
46
|
+
VALUE integration_qawo(int argc, VALUE *argv, VALUE self);
|
|
47
|
+
VALUE integration_qawf(int argc, VALUE *argv, VALUE self);
|
|
48
|
+
VALUE integration_cquad(int argc, VALUE *argv, VALUE self);
|
|
49
|
+
VALUE integration_romberg(int argc, VALUE *argv, VALUE self);
|
|
50
|
+
VALUE integration_glfixed(int argc, VALUE *argv, VALUE self);
|
|
51
|
+
|
|
52
|
+
#endif
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
void integration_options_parse(VALUE options, integration_options *parsed,
|
|
4
|
+
double default_epsabs, double default_epsrel,
|
|
5
|
+
size_t default_limit) {
|
|
6
|
+
VALUE epsabs_value = Qundef;
|
|
7
|
+
VALUE epsrel_value = Qundef;
|
|
8
|
+
VALUE limit_value = Qundef;
|
|
9
|
+
ID keywords[] = {rb_intern("epsabs"), rb_intern("epsrel"),
|
|
10
|
+
rb_intern("limit")};
|
|
11
|
+
VALUE keyword_values[3];
|
|
12
|
+
|
|
13
|
+
if (!NIL_P(options)) {
|
|
14
|
+
rb_get_kwargs(options, keywords, 0, 3, keyword_values);
|
|
15
|
+
epsabs_value = keyword_values[0];
|
|
16
|
+
epsrel_value = keyword_values[1];
|
|
17
|
+
limit_value = keyword_values[2];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
parsed->epsabs =
|
|
21
|
+
epsabs_value == Qundef ? default_epsabs : NUM2DBL(epsabs_value);
|
|
22
|
+
parsed->epsrel =
|
|
23
|
+
epsrel_value == Qundef ? default_epsrel : NUM2DBL(epsrel_value);
|
|
24
|
+
parsed->limit =
|
|
25
|
+
limit_value == Qundef ? default_limit : NUM2SIZET(limit_value);
|
|
26
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
gsl_function *function;
|
|
5
|
+
double a;
|
|
6
|
+
double b;
|
|
7
|
+
double epsabs;
|
|
8
|
+
double epsrel;
|
|
9
|
+
size_t limit;
|
|
10
|
+
int key;
|
|
11
|
+
gsl_integration_workspace *workspace;
|
|
12
|
+
double *result;
|
|
13
|
+
double *error;
|
|
14
|
+
} integration_qag_params;
|
|
15
|
+
|
|
16
|
+
static VALUE integration_run_qag(VALUE data) {
|
|
17
|
+
integration_qag_params *params = (integration_qag_params *)data;
|
|
18
|
+
|
|
19
|
+
(void)gsl_integration_qag(params->function, params->a, params->b,
|
|
20
|
+
params->epsabs, params->epsrel, params->limit,
|
|
21
|
+
params->key, params->workspace, params->result,
|
|
22
|
+
params->error);
|
|
23
|
+
|
|
24
|
+
return Qnil;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
VALUE integration_qag(int argc, VALUE *argv, VALUE self) {
|
|
28
|
+
VALUE a;
|
|
29
|
+
VALUE b;
|
|
30
|
+
VALUE options;
|
|
31
|
+
VALUE epsabs_value = Qundef;
|
|
32
|
+
VALUE epsrel_value = Qundef;
|
|
33
|
+
VALUE limit_value = Qundef;
|
|
34
|
+
VALUE key_value = Qundef;
|
|
35
|
+
ID keywords[] = {rb_intern("epsabs"), rb_intern("epsrel"), rb_intern("limit"),
|
|
36
|
+
rb_intern("key")};
|
|
37
|
+
VALUE keyword_values[4];
|
|
38
|
+
double epsabs;
|
|
39
|
+
double epsrel;
|
|
40
|
+
size_t limit;
|
|
41
|
+
int key;
|
|
42
|
+
gsl_integration_workspace *workspace;
|
|
43
|
+
gsl_function function;
|
|
44
|
+
integration_callback_params params;
|
|
45
|
+
integration_qag_params qag_params;
|
|
46
|
+
double result;
|
|
47
|
+
double error;
|
|
48
|
+
|
|
49
|
+
(void)self;
|
|
50
|
+
|
|
51
|
+
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
52
|
+
|
|
53
|
+
if (!NIL_P(options)) {
|
|
54
|
+
rb_get_kwargs(options, keywords, 0, 4, keyword_values);
|
|
55
|
+
epsabs_value = keyword_values[0];
|
|
56
|
+
epsrel_value = keyword_values[1];
|
|
57
|
+
limit_value = keyword_values[2];
|
|
58
|
+
key_value = keyword_values[3];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
epsabs = epsabs_value == Qundef ? 0.0 : NUM2DBL(epsabs_value);
|
|
62
|
+
epsrel = epsrel_value == Qundef ? 1e-8 : NUM2DBL(epsrel_value);
|
|
63
|
+
limit = limit_value == Qundef ? 1000 : NUM2SIZET(limit_value);
|
|
64
|
+
key = key_value == Qundef ? GSL_INTEG_GAUSS61 : NUM2INT(key_value);
|
|
65
|
+
|
|
66
|
+
integration_function_init(&function, ¶ms);
|
|
67
|
+
|
|
68
|
+
workspace = gsl_integration_workspace_alloc(limit);
|
|
69
|
+
|
|
70
|
+
qag_params.function = &function;
|
|
71
|
+
qag_params.a = NUM2DBL(a);
|
|
72
|
+
qag_params.b = NUM2DBL(b);
|
|
73
|
+
qag_params.epsabs = epsabs;
|
|
74
|
+
qag_params.epsrel = epsrel;
|
|
75
|
+
qag_params.limit = limit;
|
|
76
|
+
qag_params.key = key;
|
|
77
|
+
qag_params.workspace = workspace;
|
|
78
|
+
qag_params.result = &result;
|
|
79
|
+
qag_params.error = &error;
|
|
80
|
+
|
|
81
|
+
rb_ensure(integration_run_qag, (VALUE)&qag_params, integration_free_workspace,
|
|
82
|
+
(VALUE)workspace);
|
|
83
|
+
|
|
84
|
+
RB_GC_GUARD(params.block);
|
|
85
|
+
RB_GC_GUARD(params.exception);
|
|
86
|
+
|
|
87
|
+
integration_finish_callback(¶ms, 0);
|
|
88
|
+
|
|
89
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
90
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
gsl_function *function;
|
|
5
|
+
double epsabs;
|
|
6
|
+
double epsrel;
|
|
7
|
+
size_t limit;
|
|
8
|
+
gsl_integration_workspace *workspace;
|
|
9
|
+
double *result;
|
|
10
|
+
double *error;
|
|
11
|
+
} integration_qagi_params;
|
|
12
|
+
|
|
13
|
+
static VALUE integration_run_qagi(VALUE data) {
|
|
14
|
+
integration_qagi_params *params = (integration_qagi_params *)data;
|
|
15
|
+
|
|
16
|
+
(void)gsl_integration_qagi(params->function, params->epsabs, params->epsrel,
|
|
17
|
+
params->limit, params->workspace, params->result,
|
|
18
|
+
params->error);
|
|
19
|
+
|
|
20
|
+
return Qnil;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static VALUE integration_run_qagi_with_workspace(VALUE data) {
|
|
24
|
+
integration_qagi_params *params = (integration_qagi_params *)data;
|
|
25
|
+
|
|
26
|
+
return rb_ensure(integration_run_qagi, data, integration_free_workspace,
|
|
27
|
+
(VALUE)params->workspace);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
VALUE integration_qagi(int argc, VALUE *argv, VALUE self) {
|
|
31
|
+
VALUE options;
|
|
32
|
+
integration_options parsed_options;
|
|
33
|
+
double epsabs;
|
|
34
|
+
double epsrel;
|
|
35
|
+
size_t limit;
|
|
36
|
+
gsl_integration_workspace *workspace;
|
|
37
|
+
gsl_function function;
|
|
38
|
+
integration_callback_params params;
|
|
39
|
+
integration_qagi_params qagi_params;
|
|
40
|
+
double result;
|
|
41
|
+
double error;
|
|
42
|
+
int state = 0;
|
|
43
|
+
|
|
44
|
+
(void)self;
|
|
45
|
+
|
|
46
|
+
rb_scan_args(argc, argv, "0:", &options);
|
|
47
|
+
|
|
48
|
+
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
49
|
+
epsabs = parsed_options.epsabs;
|
|
50
|
+
epsrel = parsed_options.epsrel;
|
|
51
|
+
limit = parsed_options.limit;
|
|
52
|
+
|
|
53
|
+
integration_function_init(&function, ¶ms);
|
|
54
|
+
|
|
55
|
+
workspace = gsl_integration_workspace_alloc(limit);
|
|
56
|
+
|
|
57
|
+
qagi_params.function = &function;
|
|
58
|
+
qagi_params.epsabs = epsabs;
|
|
59
|
+
qagi_params.epsrel = epsrel;
|
|
60
|
+
qagi_params.limit = limit;
|
|
61
|
+
qagi_params.workspace = workspace;
|
|
62
|
+
qagi_params.result = &result;
|
|
63
|
+
qagi_params.error = &error;
|
|
64
|
+
|
|
65
|
+
rb_protect(integration_run_qagi_with_workspace, (VALUE)&qagi_params, &state);
|
|
66
|
+
|
|
67
|
+
RB_GC_GUARD(params.block);
|
|
68
|
+
RB_GC_GUARD(params.exception);
|
|
69
|
+
|
|
70
|
+
integration_finish_callback(¶ms, state);
|
|
71
|
+
|
|
72
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
73
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
gsl_function *function;
|
|
5
|
+
double b;
|
|
6
|
+
double epsabs;
|
|
7
|
+
double epsrel;
|
|
8
|
+
size_t limit;
|
|
9
|
+
gsl_integration_workspace *workspace;
|
|
10
|
+
double *result;
|
|
11
|
+
double *error;
|
|
12
|
+
} integration_qagil_params;
|
|
13
|
+
|
|
14
|
+
static VALUE integration_run_qagil(VALUE data) {
|
|
15
|
+
integration_qagil_params *params = (integration_qagil_params *)data;
|
|
16
|
+
(void)gsl_integration_qagil(params->function, params->b, params->epsabs,
|
|
17
|
+
params->epsrel, params->limit, params->workspace,
|
|
18
|
+
params->result, params->error);
|
|
19
|
+
return Qnil;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static VALUE integration_run_qagil_with_workspace(VALUE data) {
|
|
23
|
+
integration_qagil_params *params = (integration_qagil_params *)data;
|
|
24
|
+
return rb_ensure(integration_run_qagil, data, integration_free_workspace,
|
|
25
|
+
(VALUE)params->workspace);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
VALUE integration_qagil(int argc, VALUE *argv, VALUE self) {
|
|
29
|
+
VALUE b;
|
|
30
|
+
VALUE options;
|
|
31
|
+
integration_options parsed_options;
|
|
32
|
+
double epsabs;
|
|
33
|
+
double epsrel;
|
|
34
|
+
size_t limit;
|
|
35
|
+
gsl_integration_workspace *workspace;
|
|
36
|
+
gsl_function function;
|
|
37
|
+
integration_callback_params params;
|
|
38
|
+
integration_qagil_params qagil_params;
|
|
39
|
+
double result;
|
|
40
|
+
double error;
|
|
41
|
+
int state = 0;
|
|
42
|
+
(void)self;
|
|
43
|
+
|
|
44
|
+
rb_scan_args(argc, argv, "1:", &b, &options);
|
|
45
|
+
|
|
46
|
+
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
47
|
+
epsabs = parsed_options.epsabs;
|
|
48
|
+
epsrel = parsed_options.epsrel;
|
|
49
|
+
limit = parsed_options.limit;
|
|
50
|
+
|
|
51
|
+
integration_function_init(&function, ¶ms);
|
|
52
|
+
|
|
53
|
+
workspace = gsl_integration_workspace_alloc(limit);
|
|
54
|
+
qagil_params.function = &function;
|
|
55
|
+
qagil_params.b = NUM2DBL(b);
|
|
56
|
+
qagil_params.epsabs = epsabs;
|
|
57
|
+
qagil_params.epsrel = epsrel;
|
|
58
|
+
qagil_params.limit = limit;
|
|
59
|
+
qagil_params.workspace = workspace;
|
|
60
|
+
qagil_params.result = &result;
|
|
61
|
+
qagil_params.error = &error;
|
|
62
|
+
|
|
63
|
+
rb_protect(integration_run_qagil_with_workspace, (VALUE)&qagil_params,
|
|
64
|
+
&state);
|
|
65
|
+
RB_GC_GUARD(params.block);
|
|
66
|
+
RB_GC_GUARD(params.exception);
|
|
67
|
+
integration_finish_callback(¶ms, state);
|
|
68
|
+
|
|
69
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
70
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
gsl_function *function;
|
|
5
|
+
double a;
|
|
6
|
+
double epsabs;
|
|
7
|
+
double epsrel;
|
|
8
|
+
size_t limit;
|
|
9
|
+
gsl_integration_workspace *workspace;
|
|
10
|
+
double *result;
|
|
11
|
+
double *error;
|
|
12
|
+
} integration_qagiu_params;
|
|
13
|
+
|
|
14
|
+
static VALUE integration_run_qagiu(VALUE data) {
|
|
15
|
+
integration_qagiu_params *params = (integration_qagiu_params *)data;
|
|
16
|
+
(void)gsl_integration_qagiu(params->function, params->a, params->epsabs,
|
|
17
|
+
params->epsrel, params->limit, params->workspace,
|
|
18
|
+
params->result, params->error);
|
|
19
|
+
return Qnil;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static VALUE integration_run_qagiu_with_workspace(VALUE data) {
|
|
23
|
+
integration_qagiu_params *params = (integration_qagiu_params *)data;
|
|
24
|
+
return rb_ensure(integration_run_qagiu, data, integration_free_workspace,
|
|
25
|
+
(VALUE)params->workspace);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
VALUE integration_qagiu(int argc, VALUE *argv, VALUE self) {
|
|
29
|
+
VALUE a;
|
|
30
|
+
VALUE options;
|
|
31
|
+
integration_options parsed_options;
|
|
32
|
+
double epsabs;
|
|
33
|
+
double epsrel;
|
|
34
|
+
size_t limit;
|
|
35
|
+
gsl_integration_workspace *workspace;
|
|
36
|
+
gsl_function function;
|
|
37
|
+
integration_callback_params params;
|
|
38
|
+
integration_qagiu_params qagiu_params;
|
|
39
|
+
double result;
|
|
40
|
+
double error;
|
|
41
|
+
int state = 0;
|
|
42
|
+
(void)self;
|
|
43
|
+
|
|
44
|
+
rb_scan_args(argc, argv, "1:", &a, &options);
|
|
45
|
+
|
|
46
|
+
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
47
|
+
epsabs = parsed_options.epsabs;
|
|
48
|
+
epsrel = parsed_options.epsrel;
|
|
49
|
+
limit = parsed_options.limit;
|
|
50
|
+
|
|
51
|
+
integration_function_init(&function, ¶ms);
|
|
52
|
+
|
|
53
|
+
workspace = gsl_integration_workspace_alloc(limit);
|
|
54
|
+
qagiu_params.function = &function;
|
|
55
|
+
qagiu_params.a = NUM2DBL(a);
|
|
56
|
+
qagiu_params.epsabs = epsabs;
|
|
57
|
+
qagiu_params.epsrel = epsrel;
|
|
58
|
+
qagiu_params.limit = limit;
|
|
59
|
+
qagiu_params.workspace = workspace;
|
|
60
|
+
qagiu_params.result = &result;
|
|
61
|
+
qagiu_params.error = &error;
|
|
62
|
+
|
|
63
|
+
rb_protect(integration_run_qagiu_with_workspace, (VALUE)&qagiu_params,
|
|
64
|
+
&state);
|
|
65
|
+
RB_GC_GUARD(params.block);
|
|
66
|
+
RB_GC_GUARD(params.exception);
|
|
67
|
+
integration_finish_callback(¶ms, state);
|
|
68
|
+
|
|
69
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
70
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
#include <math.h>
|
|
4
|
+
|
|
5
|
+
typedef struct {
|
|
6
|
+
VALUE points_array;
|
|
7
|
+
gsl_function *function;
|
|
8
|
+
double *points;
|
|
9
|
+
size_t point_count;
|
|
10
|
+
double epsabs;
|
|
11
|
+
double epsrel;
|
|
12
|
+
size_t limit;
|
|
13
|
+
gsl_integration_workspace *workspace;
|
|
14
|
+
double *result;
|
|
15
|
+
double *error;
|
|
16
|
+
} integration_qagp_params;
|
|
17
|
+
|
|
18
|
+
static void integration_validate_qagp_points(VALUE points) {
|
|
19
|
+
long point_count;
|
|
20
|
+
long index;
|
|
21
|
+
double previous = 0.0;
|
|
22
|
+
|
|
23
|
+
if (!RB_TYPE_P(points, T_ARRAY)) {
|
|
24
|
+
rb_raise(integration_error_class(), "points must be an Array");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
point_count = RARRAY_LEN(points);
|
|
28
|
+
if (point_count < 2) {
|
|
29
|
+
rb_raise(integration_error_class(),
|
|
30
|
+
"points must contain at least two values");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (index = 0; index < point_count; index++) {
|
|
34
|
+
VALUE point = rb_ary_entry(points, index);
|
|
35
|
+
double current;
|
|
36
|
+
|
|
37
|
+
if (!rb_obj_is_kind_of(point, rb_cNumeric)) {
|
|
38
|
+
rb_raise(integration_error_class(),
|
|
39
|
+
"points must contain only numeric values");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
current = NUM2DBL(point);
|
|
43
|
+
if (!isfinite(current)) {
|
|
44
|
+
rb_raise(integration_error_class(),
|
|
45
|
+
"points must contain only finite values");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (index > 0 && !(previous < current)) {
|
|
49
|
+
rb_raise(integration_error_class(), "points must be strictly increasing");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
previous = current;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static VALUE integration_run_qagp(VALUE data) {
|
|
57
|
+
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
58
|
+
size_t index;
|
|
59
|
+
|
|
60
|
+
params->points = ALLOC_N(double, params->point_count);
|
|
61
|
+
for (index = 0; index < params->point_count; index++) {
|
|
62
|
+
params->points[index] =
|
|
63
|
+
NUM2DBL(rb_ary_entry(params->points_array, (long)index));
|
|
64
|
+
}
|
|
65
|
+
params->workspace = gsl_integration_workspace_alloc(params->limit);
|
|
66
|
+
(void)gsl_integration_qagp(params->function, params->points,
|
|
67
|
+
params->point_count, params->epsabs,
|
|
68
|
+
params->epsrel, params->limit, params->workspace,
|
|
69
|
+
params->result, params->error);
|
|
70
|
+
return Qnil;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static VALUE integration_free_qagp_resources(VALUE data) {
|
|
74
|
+
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
75
|
+
|
|
76
|
+
if (params->workspace != NULL) {
|
|
77
|
+
gsl_integration_workspace_free(params->workspace);
|
|
78
|
+
}
|
|
79
|
+
if (params->points != NULL) {
|
|
80
|
+
xfree(params->points);
|
|
81
|
+
}
|
|
82
|
+
return Qnil;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static VALUE integration_run_qagp_with_resources(VALUE data) {
|
|
86
|
+
return rb_ensure(integration_run_qagp, data, integration_free_qagp_resources,
|
|
87
|
+
data);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
91
|
+
VALUE points;
|
|
92
|
+
VALUE options;
|
|
93
|
+
integration_options parsed_options;
|
|
94
|
+
double epsabs;
|
|
95
|
+
double epsrel;
|
|
96
|
+
size_t limit;
|
|
97
|
+
gsl_function function;
|
|
98
|
+
integration_callback_params params;
|
|
99
|
+
integration_qagp_params qagp_params;
|
|
100
|
+
double result;
|
|
101
|
+
double error;
|
|
102
|
+
int state = 0;
|
|
103
|
+
|
|
104
|
+
(void)self;
|
|
105
|
+
rb_scan_args(argc, argv, "1:", &points, &options);
|
|
106
|
+
|
|
107
|
+
integration_validate_qagp_points(points);
|
|
108
|
+
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
109
|
+
epsabs = parsed_options.epsabs;
|
|
110
|
+
epsrel = parsed_options.epsrel;
|
|
111
|
+
limit = parsed_options.limit;
|
|
112
|
+
integration_function_init(&function, ¶ms);
|
|
113
|
+
qagp_params.points_array = points;
|
|
114
|
+
qagp_params.function = &function;
|
|
115
|
+
qagp_params.points = NULL;
|
|
116
|
+
qagp_params.point_count = (size_t)RARRAY_LEN(points);
|
|
117
|
+
qagp_params.epsabs = epsabs;
|
|
118
|
+
qagp_params.epsrel = epsrel;
|
|
119
|
+
qagp_params.limit = limit;
|
|
120
|
+
qagp_params.workspace = NULL;
|
|
121
|
+
qagp_params.result = &result;
|
|
122
|
+
qagp_params.error = &error;
|
|
123
|
+
rb_protect(integration_run_qagp_with_resources, (VALUE)&qagp_params, &state);
|
|
124
|
+
RB_GC_GUARD(points);
|
|
125
|
+
RB_GC_GUARD(params.block);
|
|
126
|
+
RB_GC_GUARD(params.exception);
|
|
127
|
+
integration_finish_callback(¶ms, state);
|
|
128
|
+
|
|
129
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
130
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#include "integration_internal.h"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
gsl_function *function;
|
|
5
|
+
double a;
|
|
6
|
+
double b;
|
|
7
|
+
double epsabs;
|
|
8
|
+
double epsrel;
|
|
9
|
+
size_t limit;
|
|
10
|
+
gsl_integration_workspace *workspace;
|
|
11
|
+
double *result;
|
|
12
|
+
double *error;
|
|
13
|
+
} integration_qags_params;
|
|
14
|
+
|
|
15
|
+
static VALUE integration_run_qags(VALUE data) {
|
|
16
|
+
integration_qags_params *params = (integration_qags_params *)data;
|
|
17
|
+
|
|
18
|
+
(void)gsl_integration_qags(params->function, params->a, params->b,
|
|
19
|
+
params->epsabs, params->epsrel, params->limit,
|
|
20
|
+
params->workspace, params->result, params->error);
|
|
21
|
+
|
|
22
|
+
return Qnil;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static VALUE integration_run_qags_with_workspace(VALUE data) {
|
|
26
|
+
integration_qags_params *params = (integration_qags_params *)data;
|
|
27
|
+
|
|
28
|
+
return rb_ensure(integration_run_qags, data, integration_free_workspace,
|
|
29
|
+
(VALUE)params->workspace);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
VALUE integration_qags(int argc, VALUE *argv, VALUE self) {
|
|
33
|
+
VALUE a;
|
|
34
|
+
VALUE b;
|
|
35
|
+
VALUE options;
|
|
36
|
+
integration_options parsed_options;
|
|
37
|
+
double epsabs;
|
|
38
|
+
double epsrel;
|
|
39
|
+
size_t limit;
|
|
40
|
+
gsl_integration_workspace *workspace;
|
|
41
|
+
gsl_function function;
|
|
42
|
+
integration_callback_params params;
|
|
43
|
+
integration_qags_params qags_params;
|
|
44
|
+
double result;
|
|
45
|
+
double error;
|
|
46
|
+
int state = 0;
|
|
47
|
+
|
|
48
|
+
(void)self;
|
|
49
|
+
|
|
50
|
+
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
51
|
+
|
|
52
|
+
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
53
|
+
epsabs = parsed_options.epsabs;
|
|
54
|
+
epsrel = parsed_options.epsrel;
|
|
55
|
+
limit = parsed_options.limit;
|
|
56
|
+
|
|
57
|
+
integration_function_init(&function, ¶ms);
|
|
58
|
+
|
|
59
|
+
workspace = gsl_integration_workspace_alloc(limit);
|
|
60
|
+
|
|
61
|
+
qags_params.function = &function;
|
|
62
|
+
qags_params.a = NUM2DBL(a);
|
|
63
|
+
qags_params.b = NUM2DBL(b);
|
|
64
|
+
qags_params.epsabs = epsabs;
|
|
65
|
+
qags_params.epsrel = epsrel;
|
|
66
|
+
qags_params.limit = limit;
|
|
67
|
+
qags_params.workspace = workspace;
|
|
68
|
+
qags_params.result = &result;
|
|
69
|
+
qags_params.error = &error;
|
|
70
|
+
|
|
71
|
+
rb_protect(integration_run_qags_with_workspace, (VALUE)&qags_params, &state);
|
|
72
|
+
|
|
73
|
+
RB_GC_GUARD(params.block);
|
|
74
|
+
RB_GC_GUARD(params.exception);
|
|
75
|
+
|
|
76
|
+
integration_finish_callback(¶ms, state);
|
|
77
|
+
|
|
78
|
+
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
79
|
+
}
|