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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ed1ccbd179314a5925c135faa809ff255bb9acf626c475af39237c8e397f89a
4
- data.tar.gz: 891a0e74db19f6d5c5b40aeff66a2610dbf063c5d2ccd3b9dfdae0a730a880fd
3
+ metadata.gz: 24601b3a87462ee4bc6077999599478d3c08776b8da2caa648e56dbfaacec731
4
+ data.tar.gz: 97d7fe3772e374a35ab108ea0a4238fbbceb04598fc2637c3f4d76285cc17f66
5
5
  SHA512:
6
- metadata.gz: 86207b0346bcff38a8892e36c8721d2327010b7367a74b91344db9c799ae2ea0390203572ce275efad201a47bc480f66e26b1daad753cfd63c878c7b78575793
7
- data.tar.gz: 532c33c4e35c701e901cf10d771a9c982533b927353dbbe0d53173684dc2ab66a90231e617906a10cc3d530aa05f364ea83735982e3721b421e06e1cbb2b983a
6
+ metadata.gz: 86447bf3974787c1067ceecacf700b3583fc2365fb0699f7fac10ed33c54b03c83a9ea5467598c0f9f687222d8ad6fed5c14feeca617d61d7ad39f01accb9ea1
7
+ data.tar.gz: 682f48569710825aac5fd2905dcfcab621abe47cea6f48f332b367d6da1747afe38512d08a6e84e1911b6ccd331d88fdb329b714bfa5619534ed8cea41227708
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
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
+
5
11
  ## [0.3.0] - 2026-11-05
6
12
 
7
13
  ### Added in 0.3.0
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 \\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
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)^\\alpha (b-x)^\\beta
224
- \\log^\\mu(x-a) \\log^\\nu(b-x).
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
- \\frac{1}{\\sqrt{x(1-x)}}
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
- static const gsl_integration_fixed_type *integration_fixed_type(VALUE type) {
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
- 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;
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[] = {rb_intern("order"), rb_intern("a"), rb_intern("b"),
76
- rb_intern("alpha"), rb_intern("beta")};
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
- fixed_params.type = integration_fixed_type(type);
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, rb_intern("<="), 1, INT2FIX(0)))) {
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, &params);
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
- 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;
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);
@@ -3,7 +3,7 @@
3
3
  module Numo
4
4
  module GSL
5
5
  module Integration
6
- VERSION = "0.3.0"
6
+ VERSION = "0.3.1"
7
7
  end
8
8
  end
9
9
  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.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takahiro SATOH