numo-gsl-integration 0.1.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 +4 -4
- data/CHANGELOG.md +28 -6
- data/README.md +19 -24
- data/docs/error-handling.md +8 -14
- data/docs/routines.md +318 -214
- data/ext/numo/gsl/integration/callback.c +3 -4
- data/ext/numo/gsl/integration/cquad.c +1 -0
- data/ext/numo/gsl/integration/fixed.c +163 -0
- data/ext/numo/gsl/integration/glfixed.c +14 -3
- data/ext/numo/gsl/integration/integration.c +12 -0
- data/ext/numo/gsl/integration/integration_internal.h +3 -1
- data/ext/numo/gsl/integration/qagi.c +1 -0
- data/ext/numo/gsl/integration/qagil.c +8 -0
- data/ext/numo/gsl/integration/qagiu.c +8 -0
- data/ext/numo/gsl/integration/qagp.c +21 -9
- data/ext/numo/gsl/integration/qags.c +1 -0
- data/ext/numo/gsl/integration/qawc.c +8 -0
- data/ext/numo/gsl/integration/qawf.c +3 -0
- data/ext/numo/gsl/integration/qawo.c +3 -0
- data/ext/numo/gsl/integration/qaws.c +6 -0
- data/ext/numo/gsl/integration/romberg.c +1 -0
- data/lib/numo/gsl/integration/version.rb +1 -1
- data/lib/numo/gsl/integration.rb +0 -12
- data/sig/numo/gsl/integration.rbs +8 -18
- data/sig/numo/gsl.rbs +1 -1
- metadata +3 -22
data/docs/routines.md
CHANGED
|
@@ -1,213 +1,269 @@
|
|
|
1
|
-
# Integration routines
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```ruby
|
|
16
|
-
result, error = Numo::GSL::Integration.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
GSL [
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
end
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
result, error = Numo::GSL::Integration.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
1.0
|
|
209
|
-
|
|
210
|
-
|
|
1
|
+
# Integration routines
|
|
2
|
+
|
|
3
|
+
Load the library before calling an integration routine:
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
require "numo/gsl/integration"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Exceptions raised by an integrand are propagated to the caller. A non-numeric return value from an integrand raises `TypeError`.
|
|
10
|
+
|
|
11
|
+
## QNG integration
|
|
12
|
+
|
|
13
|
+
GSL [QNG](https://www.gnu.org/software/gsl/doc/html/integration.html#qng-non-adaptive-gauss-kronrod-integration) provides non-adaptive integration for smooth functions over a finite interval. It applies increasingly accurate Gauss-Kronrod-Patterson rules and evaluates the integrand at up to 87 points.
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
result, error, evaluations = Numo::GSL::Integration.qng(0.0, 1.0) do |x|
|
|
17
|
+
x * x
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The return value contains the integral, its estimated absolute error, and the number of integrand evaluations. The `epsabs` and `epsrel` keyword arguments control the requested absolute and relative error limits:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
result, error, evaluations = Numo::GSL::Integration.qng(
|
|
25
|
+
0.0,
|
|
26
|
+
1.0,
|
|
27
|
+
epsabs: 1e-12,
|
|
28
|
+
epsrel: 1e-12
|
|
29
|
+
) do |x|
|
|
30
|
+
x * x
|
|
31
|
+
end
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## QAG integration
|
|
35
|
+
|
|
36
|
+
GSL [QAG](https://www.gnu.org/software/gsl/doc/html/integration.html#qag-adaptive-integration) provides adaptive integration over a finite interval. `Numo::GSL::Integration.qag` exposes this routine to Ruby and returns the integral and its estimated absolute error.
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
result, error = Numo::GSL::Integration.qag(0.0, 1.0) do |x|
|
|
40
|
+
x * x
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Integration parameters can be specified with the `epsabs`, `epsrel`, `limit`, and `key` keyword arguments:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
result, error = Numo::GSL::Integration.qag(
|
|
48
|
+
0.0,
|
|
49
|
+
1.0,
|
|
50
|
+
epsabs: 1e-12,
|
|
51
|
+
epsrel: 1e-12,
|
|
52
|
+
limit: 100,
|
|
53
|
+
key: Numo::GSL::Integration::GAUSS21,
|
|
54
|
+
) do |x|
|
|
55
|
+
x * x
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The `key` keyword selects the Gauss-Kronrod integration rule and defaults to `GAUSS61`. The available values are `GAUSS15`, `GAUSS21`, `GAUSS31`, `GAUSS41`, `GAUSS51`, and `GAUSS61`.
|
|
60
|
+
|
|
61
|
+
## QAGS integration
|
|
62
|
+
|
|
63
|
+
GSL [QAGS](https://www.gnu.org/software/gsl/doc/html/integration.html#qags-adaptive-integration-with-singularities) combines adaptive subdivision with extrapolation to integrate functions with integrable singularities or discontinuities over a finite interval.
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
result, error = Numo::GSL::Integration.qags(0.0, 1.0) do |x|
|
|
67
|
+
Math.log(x) / Math.sqrt(x)
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The example integral has an endpoint singularity and an exact value of `-4.0`. The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
result, error = Numo::GSL::Integration.qags(
|
|
75
|
+
0.0,
|
|
76
|
+
1.0,
|
|
77
|
+
epsabs: 1e-12,
|
|
78
|
+
epsrel: 1e-12,
|
|
79
|
+
limit: 100
|
|
80
|
+
) do |x|
|
|
81
|
+
x * x
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## QAGP integration
|
|
86
|
+
|
|
87
|
+
GSL [QAGP](https://www.gnu.org/software/gsl/doc/html/integration.html#qagp-adaptive-integration-with-known-singular-points) applies adaptive integration when the locations of interior singularities or discontinuities are known. Pass an array containing the left endpoint, zero or more known interior singularity or discontinuity points, and the right endpoint:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
result, error = Numo::GSL::Integration.qagp(
|
|
91
|
+
[0.0, 0.5, 1.0]
|
|
92
|
+
) do |x|
|
|
93
|
+
1.0 / Math.sqrt((x - 0.5).abs)
|
|
94
|
+
end
|
|
95
|
+
```
|
|
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.
|
|
98
|
+
The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
result, error = Numo::GSL::Integration.qagp(
|
|
102
|
+
[0.0, 0.25, 0.75, 1.0],
|
|
103
|
+
epsabs: 1e-12,
|
|
104
|
+
epsrel: 1e-12,
|
|
105
|
+
limit: 100
|
|
106
|
+
) do |x|
|
|
107
|
+
x * x
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## QAGI integration
|
|
112
|
+
|
|
113
|
+
GSL [QAGI](https://www.gnu.org/software/gsl/doc/html/integration.html#qagi-adaptive-integration-on-infinite-intervals) provides adaptive integration over the infinite interval from negative infinity to positive infinity. `Numo::GSL::Integration.qagi` takes no interval endpoints and returns the integral and its estimated absolute error.
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
result, error = Numo::GSL::Integration.qagi do |x|
|
|
117
|
+
Math.exp(-(x * x))
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The example integrates the Gaussian function, whose exact value is `Math.sqrt(Math::PI)`. The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
result, error = Numo::GSL::Integration.qagi(
|
|
125
|
+
epsabs: 1e-12,
|
|
126
|
+
epsrel: 1e-12,
|
|
127
|
+
limit: 100
|
|
128
|
+
) do |x|
|
|
129
|
+
1.0 / (1.0 + (x * x))
|
|
130
|
+
end
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## QAGIU integration
|
|
134
|
+
|
|
135
|
+
GSL [QAGIU](https://www.gnu.org/software/gsl/doc/html/integration.html#qagi-adaptive-integration-on-infinite-intervals) provides adaptive integration from a finite lower bound to positive infinity. `Numo::GSL::Integration.qagiu` takes the lower bound and returns the integral and its estimated absolute error.
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
result, error = Numo::GSL::Integration.qagiu(0.0) do |x|
|
|
139
|
+
Math.exp(-x)
|
|
140
|
+
end
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The example integral has an exact value of `1.0`. The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
result, error = Numo::GSL::Integration.qagiu(
|
|
147
|
+
1.0,
|
|
148
|
+
epsabs: 1e-12,
|
|
149
|
+
epsrel: 1e-12,
|
|
150
|
+
limit: 100
|
|
151
|
+
) do |x|
|
|
152
|
+
Math.exp(-x)
|
|
153
|
+
end
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## QAGIL integration
|
|
157
|
+
|
|
158
|
+
GSL [QAGIL](https://www.gnu.org/software/gsl/doc/html/integration.html#qagi-adaptive-integration-on-infinite-intervals) provides adaptive integration from negative infinity to a finite upper bound. `Numo::GSL::Integration.qagil` takes the upper bound and returns the integral and its estimated absolute error.
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
result, error = Numo::GSL::Integration.qagil(0.0) do |x|
|
|
162
|
+
Math.exp(x)
|
|
163
|
+
end
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The example integral has an exact value of `1.0`. The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
result, error = Numo::GSL::Integration.qagil(
|
|
170
|
+
-1.0,
|
|
171
|
+
epsabs: 1e-12,
|
|
172
|
+
epsrel: 1e-12,
|
|
173
|
+
limit: 100
|
|
174
|
+
) do |x|
|
|
175
|
+
Math.exp(x)
|
|
176
|
+
end
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## QAWC integration
|
|
180
|
+
|
|
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
|
+
|
|
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)
|
|
192
|
+
```
|
|
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.
|
|
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
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
result, error = Numo::GSL::Integration.qawc(0.0, 2.0, 1.0) do |x|
|
|
199
|
+
x
|
|
200
|
+
end
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals. The following example computes the principal value of `1.0 / x` over the symmetric interval from `-1.0` to `1.0`, whose exact value is `0.0`. It specifies a positive `epsabs` because a relative error bound alone is not suitable when the expected result is zero:
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
result, error = Numo::GSL::Integration.qawc(
|
|
207
|
+
-1.0,
|
|
208
|
+
1.0,
|
|
209
|
+
0.0,
|
|
210
|
+
epsabs: 1e-12,
|
|
211
|
+
epsrel: 1e-12,
|
|
212
|
+
limit: 100
|
|
213
|
+
) do |_x|
|
|
214
|
+
1.0
|
|
215
|
+
end
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## QAWS integration
|
|
219
|
+
|
|
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
|
+
|
|
222
|
+
```math
|
|
223
|
+
(x-a)^\\alpha (b-x)^\\beta
|
|
224
|
+
\\log^\\mu(x-a) \\log^\\nu(b-x).
|
|
225
|
+
```
|
|
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`.
|
|
228
|
+
The block returns the unweighted function $f(x)$. QAWS applies the endpoint weight internally. The following example integrates
|
|
229
|
+
|
|
230
|
+
```math
|
|
231
|
+
\\frac{1}{\\sqrt{x(1-x)}}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
over the interval from `0.0` to `1.0`. Its exact value is `Math::PI`:
|
|
235
|
+
|
|
236
|
+
```ruby
|
|
237
|
+
result, error = Numo::GSL::Integration.qaws(
|
|
238
|
+
0.0,
|
|
239
|
+
1.0,
|
|
240
|
+
-0.5,
|
|
241
|
+
-0.5,
|
|
242
|
+
0,
|
|
243
|
+
0
|
|
244
|
+
) do |_x|
|
|
245
|
+
1.0
|
|
246
|
+
end
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Set `mu` to `1` to include `log(x - a)`, and set `nu` to `1` to include `log(b - x)`. The `epsabs`, `epsrel`, and `limit` keyword arguments control the requested error limits and maximum number of subintervals:
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
result, error = Numo::GSL::Integration.qaws(
|
|
253
|
+
0.0,
|
|
254
|
+
1.0,
|
|
255
|
+
0.0,
|
|
256
|
+
0.0,
|
|
257
|
+
1,
|
|
258
|
+
0,
|
|
259
|
+
epsabs: 1e-12,
|
|
260
|
+
epsrel: 1e-12,
|
|
261
|
+
limit: 100
|
|
262
|
+
) do |_x|
|
|
263
|
+
1.0
|
|
264
|
+
end
|
|
265
|
+
```
|
|
266
|
+
|
|
211
267
|
This example computes the integral of `log(x)` from `0.0` to `1.0`, whose exact value is `-1.0`.
|
|
212
268
|
|
|
213
269
|
## QAWO integration
|
|
@@ -266,12 +322,11 @@ end
|
|
|
266
322
|
```
|
|
267
323
|
|
|
268
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.
|
|
269
|
-
|
|
270
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.
|
|
271
326
|
|
|
272
327
|
## GLFIXED integration
|
|
273
328
|
|
|
274
|
-
GSL [fixed-order Gauss
|
|
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.
|
|
275
330
|
|
|
276
331
|
```ruby
|
|
277
332
|
result = Numo::GSL::Integration.glfixed(
|
|
@@ -283,6 +338,55 @@ result = Numo::GSL::Integration.glfixed(
|
|
|
283
338
|
end
|
|
284
339
|
```
|
|
285
340
|
|
|
286
|
-
The example integral has an exact value of `1.0 / 5.0`. The `order` keyword controls the number of Gauss
|
|
287
|
-
|
|
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.
|
|
288
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.
|
|
@@ -19,6 +19,7 @@ void integration_callback_params_init(integration_callback_params *params) {
|
|
|
19
19
|
void integration_function_init(gsl_function *function,
|
|
20
20
|
integration_callback_params *params) {
|
|
21
21
|
integration_callback_params_init(params);
|
|
22
|
+
|
|
22
23
|
function->function = integration_callback;
|
|
23
24
|
function->params = params;
|
|
24
25
|
}
|
|
@@ -32,6 +33,7 @@ double integration_callback(double x, void *data) {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
params->x = DBL2NUM(x);
|
|
36
|
+
|
|
35
37
|
value = rb_protect(integration_call_block, (VALUE)params, ¶ms->state);
|
|
36
38
|
|
|
37
39
|
if (params->state != 0) {
|
|
@@ -51,11 +53,8 @@ void integration_raise_callback_exception(integration_callback_params *params) {
|
|
|
51
53
|
void integration_finish_callback(integration_callback_params *params,
|
|
52
54
|
int state) {
|
|
53
55
|
integration_raise_callback_exception(params);
|
|
56
|
+
|
|
54
57
|
if (state != 0) {
|
|
55
58
|
rb_jump_tag(state);
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
|
-
|
|
59
|
-
VALUE integration_error_class(void) {
|
|
60
|
-
return rb_path2class("Numo::GSL::Integration::Error");
|
|
61
|
-
}
|
|
@@ -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;
|