numo-gsl-integration 0.1.0 → 0.2.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 +21 -5
- data/README.md +20 -26
- data/docs/error-handling.md +8 -14
- data/docs/routines.md +266 -212
- data/ext/numo/gsl/integration/callback.c +0 -16
- data/ext/numo/gsl/integration/glfixed.c +10 -20
- data/ext/numo/gsl/integration/integration.c +9 -4
- data/ext/numo/gsl/integration/integration_internal.h +1 -8
- data/ext/numo/gsl/integration/qagp.c +5 -27
- data/lib/numo/gsl/integration/version.rb +1 -1
- data/lib/numo/gsl/integration.rb +0 -12
- data/sig/numo/gsl/integration.rbs +0 -18
- data/sig/numo/gsl.rbs +1 -1
- metadata +2 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01ba50fbaebaceaa6e5d4151c60a5cda604fbdb45cb78fe0cdbce009916d0028
|
|
4
|
+
data.tar.gz: 50080c206cf316e836e6e36c7a33492665a1eaa6a832704d98046aa090c2d70b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52e2c27c1aa5bec02da2afb0c737eb607f8517f2c4ce55d2fdf26ce8ab72c5003d3ce79ff755b8430bae7479864ea90ad7b1340454e99b9b133cd0223be943df
|
|
7
|
+
data.tar.gz: 45e2d49aaa8c374e8e4591965d71dc91468fa855bd73779363ab71dbf997e1484a0ff2bb33e4925ecfa2b05c5d90533d943ea97f89efd25bb733b982d631f4e4
|
data/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.2.0] - 2026-11-05
|
|
6
|
+
|
|
7
|
+
### Changed in 0.2.0
|
|
8
|
+
|
|
9
|
+
- Removed the runtime dependency on `numo-gsl-alt`.
|
|
10
|
+
- Defined `Numo::GSL::GslError` and installed the process-wide GSL error handler in the native extension.
|
|
11
|
+
- Added the numeric GSL error code to messages raised by the integration GSL error handler.
|
|
12
|
+
- Replaced wrapper-side validation errors with `TypeError` and `ArgumentError`.
|
|
13
|
+
- Changed Markdown formatting from `markdownlint-cli2 --fix` to Prettier while retaining `markdownlint-cli2` for linting.
|
|
14
|
+
- Extended Markdown formatting and linting to all Markdown files under the project root and `docs`.
|
|
15
|
+
- Added Prettier installation to the CI workflow.
|
|
16
|
+
|
|
17
|
+
### Removed in 0.2.0
|
|
18
|
+
|
|
19
|
+
- Removed `Numo::GSL::Integration::Error`.
|
|
20
|
+
|
|
5
21
|
## [0.1.0] - 2026-11-04
|
|
6
22
|
|
|
7
|
-
### Added
|
|
23
|
+
### Added in 0.1.0
|
|
8
24
|
|
|
9
25
|
- Added fixed-order Gauss–Legendre integration for smooth functions.
|
|
10
26
|
- Added Romberg integration for smooth functions with function-evaluation counts.
|
|
@@ -24,8 +40,8 @@
|
|
|
24
40
|
- Added RBS declarations for the public integration API and RBS validation to the default Rake task.
|
|
25
41
|
- Added automated rubyfmt, clang-format, and Markdown checks, with `format:check` and `format:apply` tasks.
|
|
26
42
|
|
|
27
|
-
### Changed
|
|
43
|
+
### Changed in 0.1.0
|
|
28
44
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
45
|
+
- Loaded `numo/gsl` before the integration native extension and made `Numo::GSL::Integration::Error` inherit from `Numo::GSL::GslError`.
|
|
46
|
+
- Delegated GSL-reported integration errors to the process-wide handler installed by `numo-gsl-alt` instead of converting return statuses to `Integration::Error`.
|
|
47
|
+
- Ensured integration workspaces, weight tables, and temporary arrays are released when integration completes normally or raises an exception.
|
data/README.md
CHANGED
|
@@ -1,18 +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
|
|
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`.
|
|
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`
|
|
10
|
-
|
|
11
|
-
The `numo-gsl-alt` Ruby gem is installed as a runtime dependency. GSL itself must be installed separately.
|
|
12
|
-
|
|
13
|
-
## Why numo-gsl-alt?
|
|
14
|
-
|
|
15
|
-
This gem intentionally depends on [`numo-gsl-alt`](https://github.com/mvz/numo-gsl-alt) rather than [`numo-gsl`](https://github.com/ruby-numo/numo-gsl). The main reason is Ruby compatibility: `numo-gsl` 0.1.2 does not build with Ruby 4.0 because its generated native extension registers a three-argument C function as a one-argument Ruby method. Ruby 4.0 rejects that incompatible function-pointer type during compilation. `numo-gsl-integration` targets Ruby 3.2 or later and is developed and tested with `numo-gsl-alt` 0.1.x, including Ruby 4.0.
|
|
9
|
+
- `gsl-config` available in `PATH`
|
|
10
|
+
GSL itself must be installed separately.
|
|
16
11
|
|
|
17
12
|
## Installation
|
|
18
13
|
|
|
@@ -38,8 +33,7 @@ Load the library:
|
|
|
38
33
|
require "numo/gsl/integration"
|
|
39
34
|
```
|
|
40
35
|
|
|
41
|
-
The
|
|
42
|
-
|
|
36
|
+
The native extension defines `Numo::GSL::GslError` and installs a process-wide GSL error handler when it is loaded.
|
|
43
37
|
For example, use `qag` to integrate a function over a finite interval:
|
|
44
38
|
|
|
45
39
|
```ruby
|
|
@@ -50,22 +44,22 @@ end
|
|
|
50
44
|
|
|
51
45
|
## Supported routines
|
|
52
46
|
|
|
53
|
-
| Method
|
|
54
|
-
|
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `qags`
|
|
58
|
-
| `qagp`
|
|
59
|
-
| `qagi`
|
|
60
|
-
| `qagiu`
|
|
61
|
-
| `qagil`
|
|
62
|
-
| `qawc`
|
|
63
|
-
| `qaws`
|
|
64
|
-
| `qawo`
|
|
65
|
-
| `qawf`
|
|
66
|
-
| `cquad`
|
|
67
|
-
| `romberg` | Finite
|
|
68
|
-
| `glfixed` | Finite
|
|
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 |
|
|
69
63
|
|
|
70
64
|
See [Integration routines](docs/routines.md) for parameters and examples.
|
|
71
65
|
|
data/docs/error-handling.md
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
# GSL error handling
|
|
2
2
|
|
|
3
|
-
`numo-gsl-
|
|
3
|
+
`numo-gsl-integration` defines `Numo::GSL::GslError` as a subclass of `StandardError` and installs a process-wide GSL error handler when the native extension is loaded.
|
|
4
|
+
Errors reported by GSL are raised directly as `Numo::GSL::GslError`. The message contains the GSL source file, line number, reason, and numeric error code:
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The workspaces used by QAG, QAGS, QAGP, QAGI, QAGIU, QAGIL, QAWC, QAWS, QAWO, QAWF, CQUAD, and Romberg are released when a call completes normally or raises an exception. QAWS, QAWO, and QAWF also release their weight tables, GLFIXED releases its Gauss–Legendre table, and QAGP releases its temporary copy of the point array.
|
|
8
|
-
|
|
9
|
-
`Numo::GSL::Integration::Error` is reserved for validation or state errors detected by `numo-gsl-integration` itself. It inherits from `Numo::GSL::GslError`:
|
|
10
|
-
|
|
11
|
-
```mermaid
|
|
12
|
-
flowchart BT
|
|
13
|
-
IntegrationError["Numo::GSL::Integration::Error"] -->|inherits from| GslError["Numo::GSL::GslError"]
|
|
14
|
-
GslError -->|inherits from| StandardError
|
|
6
|
+
```text
|
|
7
|
+
file:line: reason (GSL error code)
|
|
15
8
|
```
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
`numo-gsl-integration` does not convert integration return statuses into separate exceptions.
|
|
11
|
+
The workspaces used by QAG, QAGS, QAGP, QAGI, QAGIU, QAGIL, QAWC, QAWS, QAWO, QAWF, CQUAD, and Romberg are released when a call completes normally or raises an exception. QAWS, QAWO, and QAWF also release their weight tables, GLFIXED releases its Gauss–Legendre table, and QAGP releases its temporary copy of the point array.
|
|
12
|
+
Invalid argument types raise `TypeError`. Invalid values, counts, or ordering raise `ArgumentError`. Exceptions raised by the integrand are propagated unchanged.
|
|
13
|
+
The GSL error handler is shared by the entire process. Loading this gem replaces the previously registered handler. If another GSL binding is loaded afterward, that binding may replace this gem's handler in turn.
|
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
|
-
|
|
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
|
+
|
|
151
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.
|
|
152
|
-
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`:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
+
|
|
177
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`.
|
|
178
|
-
The block returns the unweighted function $f(x)$. QAWS applies the endpoint weight internally. The following example integrates
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
0,
|
|
190
|
-
0
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
0,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
|
@@ -265,8 +321,7 @@ result, evaluations = Numo::GSL::Integration.romberg(0.0, Math::PI) do |x|
|
|
|
265
321
|
end
|
|
266
322
|
```
|
|
267
323
|
|
|
268
|
-
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
|
-
|
|
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.
|
|
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
|
|
@@ -283,6 +338,5 @@ 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–Legendre points and defaults to `10`. It must be a positive integer.
|
|
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.
|
|
@@ -1,53 +1,41 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
-
|
|
3
2
|
static VALUE integration_call_block(VALUE data) {
|
|
4
3
|
integration_callback_params *params = (integration_callback_params *)data;
|
|
5
4
|
VALUE value;
|
|
6
|
-
|
|
7
5
|
value = rb_funcall(params->block, rb_intern("call"), 1, params->x);
|
|
8
|
-
|
|
9
6
|
return rb_Float(value);
|
|
10
7
|
}
|
|
11
|
-
|
|
12
8
|
void integration_callback_params_init(integration_callback_params *params) {
|
|
13
9
|
params->block = rb_block_proc();
|
|
14
10
|
params->x = Qnil;
|
|
15
11
|
params->exception = Qnil;
|
|
16
12
|
params->state = 0;
|
|
17
13
|
}
|
|
18
|
-
|
|
19
14
|
void integration_function_init(gsl_function *function,
|
|
20
15
|
integration_callback_params *params) {
|
|
21
16
|
integration_callback_params_init(params);
|
|
22
17
|
function->function = integration_callback;
|
|
23
18
|
function->params = params;
|
|
24
19
|
}
|
|
25
|
-
|
|
26
20
|
double integration_callback(double x, void *data) {
|
|
27
21
|
integration_callback_params *params = data;
|
|
28
22
|
VALUE value;
|
|
29
|
-
|
|
30
23
|
if (params->state != 0) {
|
|
31
24
|
return 0.0;
|
|
32
25
|
}
|
|
33
|
-
|
|
34
26
|
params->x = DBL2NUM(x);
|
|
35
27
|
value = rb_protect(integration_call_block, (VALUE)params, ¶ms->state);
|
|
36
|
-
|
|
37
28
|
if (params->state != 0) {
|
|
38
29
|
params->exception = rb_errinfo();
|
|
39
30
|
return 0.0;
|
|
40
31
|
}
|
|
41
|
-
|
|
42
32
|
return NUM2DBL(value);
|
|
43
33
|
}
|
|
44
|
-
|
|
45
34
|
void integration_raise_callback_exception(integration_callback_params *params) {
|
|
46
35
|
if (params->state != 0) {
|
|
47
36
|
rb_exc_raise(params->exception);
|
|
48
37
|
}
|
|
49
38
|
}
|
|
50
|
-
|
|
51
39
|
void integration_finish_callback(integration_callback_params *params,
|
|
52
40
|
int state) {
|
|
53
41
|
integration_raise_callback_exception(params);
|
|
@@ -55,7 +43,3 @@ void integration_finish_callback(integration_callback_params *params,
|
|
|
55
43
|
rb_jump_tag(state);
|
|
56
44
|
}
|
|
57
45
|
}
|
|
58
|
-
|
|
59
|
-
VALUE integration_error_class(void) {
|
|
60
|
-
return rb_path2class("Numo::GSL::Integration::Error");
|
|
61
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
-
|
|
3
2
|
typedef struct {
|
|
4
3
|
gsl_function *function;
|
|
5
4
|
double a;
|
|
@@ -8,23 +7,17 @@ typedef struct {
|
|
|
8
7
|
gsl_integration_glfixed_table *table;
|
|
9
8
|
double *result;
|
|
10
9
|
} integration_glfixed_params;
|
|
11
|
-
|
|
12
10
|
static VALUE integration_run_glfixed(VALUE data) {
|
|
13
11
|
integration_glfixed_params *params = (integration_glfixed_params *)data;
|
|
14
|
-
|
|
15
12
|
*(params->result) = gsl_integration_glfixed(params->function, params->a,
|
|
16
13
|
params->b, params->table);
|
|
17
|
-
|
|
18
14
|
return Qnil;
|
|
19
15
|
}
|
|
20
|
-
|
|
21
16
|
static VALUE integration_run_glfixed_with_table(VALUE data) {
|
|
22
17
|
integration_glfixed_params *params = (integration_glfixed_params *)data;
|
|
23
|
-
|
|
24
18
|
return rb_ensure(integration_run_glfixed, data,
|
|
25
19
|
integration_free_glfixed_table, (VALUE)params->table);
|
|
26
20
|
}
|
|
27
|
-
|
|
28
21
|
VALUE integration_glfixed(int argc, VALUE *argv, VALUE self) {
|
|
29
22
|
VALUE a;
|
|
30
23
|
VALUE b;
|
|
@@ -38,37 +31,34 @@ VALUE integration_glfixed(int argc, VALUE *argv, VALUE self) {
|
|
|
38
31
|
integration_glfixed_params glfixed_params;
|
|
39
32
|
double result;
|
|
40
33
|
int state = 0;
|
|
41
|
-
|
|
42
34
|
(void)self;
|
|
43
|
-
|
|
44
35
|
rb_scan_args(argc, argv, "2:", &a, &b, &options);
|
|
45
|
-
|
|
46
36
|
if (!NIL_P(options)) {
|
|
47
37
|
rb_get_kwargs(options, keywords, 0, 1, keyword_values);
|
|
48
38
|
order_value = keyword_values[0];
|
|
49
39
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
if (order_value == Qundef) {
|
|
41
|
+
order = 10;
|
|
42
|
+
} else {
|
|
43
|
+
if (!RB_INTEGER_TYPE_P(order_value)) {
|
|
44
|
+
rb_raise(rb_eTypeError, "order must be an Integer");
|
|
45
|
+
}
|
|
46
|
+
if (RTEST(rb_funcall(order_value, rb_intern("<="), 1, INT2FIX(0)))) {
|
|
47
|
+
rb_raise(rb_eArgError, "order must be positive");
|
|
48
|
+
}
|
|
49
|
+
order = NUM2SIZET(order_value);
|
|
54
50
|
}
|
|
55
|
-
|
|
56
51
|
integration_function_init(&function, ¶ms);
|
|
57
|
-
|
|
58
52
|
glfixed_params.function = &function;
|
|
59
53
|
glfixed_params.a = NUM2DBL(a);
|
|
60
54
|
glfixed_params.b = NUM2DBL(b);
|
|
61
55
|
glfixed_params.order = order;
|
|
62
56
|
glfixed_params.table = gsl_integration_glfixed_table_alloc(order);
|
|
63
57
|
glfixed_params.result = &result;
|
|
64
|
-
|
|
65
58
|
rb_protect(integration_run_glfixed_with_table, (VALUE)&glfixed_params,
|
|
66
59
|
&state);
|
|
67
|
-
|
|
68
60
|
RB_GC_GUARD(params.block);
|
|
69
61
|
RB_GC_GUARD(params.exception);
|
|
70
|
-
|
|
71
62
|
integration_finish_callback(¶ms, state);
|
|
72
|
-
|
|
73
63
|
return DBL2NUM(result);
|
|
74
64
|
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
-
|
|
2
|
+
static VALUE numo_eGslError;
|
|
3
|
+
static _Noreturn void integration_gsl_error_handler(const char *reason,
|
|
4
|
+
const char *file, int line,
|
|
5
|
+
int gsl_errno) {
|
|
6
|
+
rb_raise(numo_eGslError, "%s:%d: %s (GSL error %d)", file, line, reason,
|
|
7
|
+
gsl_errno);
|
|
8
|
+
}
|
|
3
9
|
void Init_integration(void) {
|
|
4
10
|
VALUE mNumo;
|
|
5
11
|
VALUE mGSL;
|
|
6
12
|
VALUE mIntegration;
|
|
7
|
-
|
|
8
13
|
mNumo = rb_define_module("Numo");
|
|
9
14
|
mGSL = rb_define_module_under(mNumo, "GSL");
|
|
10
15
|
mIntegration = rb_define_module_under(mGSL, "Integration");
|
|
11
|
-
|
|
16
|
+
numo_eGslError = rb_define_class_under(mGSL, "GslError", rb_eStandardError);
|
|
17
|
+
gsl_set_error_handler(&integration_gsl_error_handler);
|
|
12
18
|
rb_define_const(mIntegration, "GAUSS15", INT2NUM(GSL_INTEG_GAUSS15));
|
|
13
19
|
rb_define_const(mIntegration, "GAUSS21", INT2NUM(GSL_INTEG_GAUSS21));
|
|
14
20
|
rb_define_const(mIntegration, "GAUSS31", INT2NUM(GSL_INTEG_GAUSS31));
|
|
@@ -17,7 +23,6 @@ void Init_integration(void) {
|
|
|
17
23
|
rb_define_const(mIntegration, "GAUSS61", INT2NUM(GSL_INTEG_GAUSS61));
|
|
18
24
|
rb_define_const(mIntegration, "COSINE", INT2NUM(GSL_INTEG_COSINE));
|
|
19
25
|
rb_define_const(mIntegration, "SINE", INT2NUM(GSL_INTEG_SINE));
|
|
20
|
-
|
|
21
26
|
rb_define_singleton_method(mIntegration, "qag", integration_qag, -1);
|
|
22
27
|
rb_define_singleton_method(mIntegration, "qng", integration_qng, -1);
|
|
23
28
|
rb_define_singleton_method(mIntegration, "qags", integration_qags, -1);
|
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
#ifndef NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
2
2
|
#define NUMO_GSL_INTEGRATION_INTERNAL_H
|
|
3
|
-
|
|
3
|
+
#include <gsl/gsl_errno.h>
|
|
4
4
|
#include <gsl/gsl_integration.h>
|
|
5
5
|
#include <ruby.h>
|
|
6
|
-
|
|
7
6
|
typedef struct {
|
|
8
7
|
double epsabs;
|
|
9
8
|
double epsrel;
|
|
10
9
|
size_t limit;
|
|
11
10
|
} integration_options;
|
|
12
|
-
|
|
13
11
|
void integration_options_parse(VALUE options, integration_options *parsed,
|
|
14
12
|
double default_epsabs, double default_epsrel,
|
|
15
13
|
size_t default_limit);
|
|
16
|
-
|
|
17
14
|
typedef struct {
|
|
18
15
|
VALUE block;
|
|
19
16
|
VALUE x;
|
|
20
17
|
VALUE exception;
|
|
21
18
|
int state;
|
|
22
19
|
} integration_callback_params;
|
|
23
|
-
|
|
24
20
|
void integration_callback_params_init(integration_callback_params *params);
|
|
25
21
|
void integration_function_init(gsl_function *function,
|
|
26
22
|
integration_callback_params *params);
|
|
@@ -28,12 +24,10 @@ double integration_callback(double x, void *data);
|
|
|
28
24
|
void integration_raise_callback_exception(integration_callback_params *params);
|
|
29
25
|
void integration_finish_callback(integration_callback_params *params,
|
|
30
26
|
int state);
|
|
31
|
-
VALUE integration_error_class(void);
|
|
32
27
|
VALUE integration_free_workspace(VALUE data);
|
|
33
28
|
VALUE integration_free_cquad_workspace(VALUE data);
|
|
34
29
|
VALUE integration_free_romberg_workspace(VALUE data);
|
|
35
30
|
VALUE integration_free_glfixed_table(VALUE data);
|
|
36
|
-
|
|
37
31
|
VALUE integration_qag(int argc, VALUE *argv, VALUE self);
|
|
38
32
|
VALUE integration_qng(int argc, VALUE *argv, VALUE self);
|
|
39
33
|
VALUE integration_qags(int argc, VALUE *argv, VALUE self);
|
|
@@ -48,5 +42,4 @@ VALUE integration_qawf(int argc, VALUE *argv, VALUE self);
|
|
|
48
42
|
VALUE integration_cquad(int argc, VALUE *argv, VALUE self);
|
|
49
43
|
VALUE integration_romberg(int argc, VALUE *argv, VALUE self);
|
|
50
44
|
VALUE integration_glfixed(int argc, VALUE *argv, VALUE self);
|
|
51
|
-
|
|
52
45
|
#endif
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#include "integration_internal.h"
|
|
2
|
-
|
|
3
2
|
#include <math.h>
|
|
4
|
-
|
|
5
3
|
typedef struct {
|
|
6
4
|
VALUE points_array;
|
|
7
5
|
gsl_function *function;
|
|
@@ -14,49 +12,36 @@ typedef struct {
|
|
|
14
12
|
double *result;
|
|
15
13
|
double *error;
|
|
16
14
|
} integration_qagp_params;
|
|
17
|
-
|
|
18
15
|
static void integration_validate_qagp_points(VALUE points) {
|
|
19
16
|
long point_count;
|
|
20
17
|
long index;
|
|
21
18
|
double previous = 0.0;
|
|
22
|
-
|
|
23
19
|
if (!RB_TYPE_P(points, T_ARRAY)) {
|
|
24
|
-
rb_raise(
|
|
20
|
+
rb_raise(rb_eTypeError, "points must be an Array");
|
|
25
21
|
}
|
|
26
|
-
|
|
27
22
|
point_count = RARRAY_LEN(points);
|
|
28
23
|
if (point_count < 2) {
|
|
29
|
-
rb_raise(
|
|
30
|
-
"points must contain at least two values");
|
|
24
|
+
rb_raise(rb_eArgError, "points must contain at least two values");
|
|
31
25
|
}
|
|
32
|
-
|
|
33
26
|
for (index = 0; index < point_count; index++) {
|
|
34
27
|
VALUE point = rb_ary_entry(points, index);
|
|
35
28
|
double current;
|
|
36
|
-
|
|
37
29
|
if (!rb_obj_is_kind_of(point, rb_cNumeric)) {
|
|
38
|
-
rb_raise(
|
|
39
|
-
"points must contain only numeric values");
|
|
30
|
+
rb_raise(rb_eTypeError, "points must contain only numeric values");
|
|
40
31
|
}
|
|
41
|
-
|
|
42
32
|
current = NUM2DBL(point);
|
|
43
33
|
if (!isfinite(current)) {
|
|
44
|
-
rb_raise(
|
|
45
|
-
"points must contain only finite values");
|
|
34
|
+
rb_raise(rb_eArgError, "points must contain only finite values");
|
|
46
35
|
}
|
|
47
|
-
|
|
48
36
|
if (index > 0 && !(previous < current)) {
|
|
49
|
-
rb_raise(
|
|
37
|
+
rb_raise(rb_eArgError, "points must be strictly increasing");
|
|
50
38
|
}
|
|
51
|
-
|
|
52
39
|
previous = current;
|
|
53
40
|
}
|
|
54
41
|
}
|
|
55
|
-
|
|
56
42
|
static VALUE integration_run_qagp(VALUE data) {
|
|
57
43
|
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
58
44
|
size_t index;
|
|
59
|
-
|
|
60
45
|
params->points = ALLOC_N(double, params->point_count);
|
|
61
46
|
for (index = 0; index < params->point_count; index++) {
|
|
62
47
|
params->points[index] =
|
|
@@ -69,10 +54,8 @@ static VALUE integration_run_qagp(VALUE data) {
|
|
|
69
54
|
params->result, params->error);
|
|
70
55
|
return Qnil;
|
|
71
56
|
}
|
|
72
|
-
|
|
73
57
|
static VALUE integration_free_qagp_resources(VALUE data) {
|
|
74
58
|
integration_qagp_params *params = (integration_qagp_params *)data;
|
|
75
|
-
|
|
76
59
|
if (params->workspace != NULL) {
|
|
77
60
|
gsl_integration_workspace_free(params->workspace);
|
|
78
61
|
}
|
|
@@ -81,12 +64,10 @@ static VALUE integration_free_qagp_resources(VALUE data) {
|
|
|
81
64
|
}
|
|
82
65
|
return Qnil;
|
|
83
66
|
}
|
|
84
|
-
|
|
85
67
|
static VALUE integration_run_qagp_with_resources(VALUE data) {
|
|
86
68
|
return rb_ensure(integration_run_qagp, data, integration_free_qagp_resources,
|
|
87
69
|
data);
|
|
88
70
|
}
|
|
89
|
-
|
|
90
71
|
VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
91
72
|
VALUE points;
|
|
92
73
|
VALUE options;
|
|
@@ -100,10 +81,8 @@ VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
|
100
81
|
double result;
|
|
101
82
|
double error;
|
|
102
83
|
int state = 0;
|
|
103
|
-
|
|
104
84
|
(void)self;
|
|
105
85
|
rb_scan_args(argc, argv, "1:", &points, &options);
|
|
106
|
-
|
|
107
86
|
integration_validate_qagp_points(points);
|
|
108
87
|
integration_options_parse(options, &parsed_options, 0.0, 1e-8, 1000);
|
|
109
88
|
epsabs = parsed_options.epsabs;
|
|
@@ -125,6 +104,5 @@ VALUE integration_qagp(int argc, VALUE *argv, VALUE self) {
|
|
|
125
104
|
RB_GC_GUARD(params.block);
|
|
126
105
|
RB_GC_GUARD(params.exception);
|
|
127
106
|
integration_finish_callback(¶ms, state);
|
|
128
|
-
|
|
129
107
|
return rb_ary_new_from_args(2, DBL2NUM(result), DBL2NUM(error));
|
|
130
108
|
}
|
data/lib/numo/gsl/integration.rb
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
2
|
require_relative "integration/version"
|
|
4
|
-
require "numo/gsl"
|
|
5
|
-
|
|
6
|
-
module Numo
|
|
7
|
-
module GSL
|
|
8
|
-
module Integration
|
|
9
|
-
class Error < Numo::GSL::GslError
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
3
|
require "numo/gsl/integration/integration"
|
|
@@ -2,10 +2,6 @@ module Numo
|
|
|
2
2
|
module GSL
|
|
3
3
|
module Integration
|
|
4
4
|
VERSION: String
|
|
5
|
-
|
|
6
|
-
class Error < ::Numo::GSL::GslError
|
|
7
|
-
end
|
|
8
|
-
|
|
9
5
|
GAUSS15: Integer
|
|
10
6
|
GAUSS21: Integer
|
|
11
7
|
GAUSS31: Integer
|
|
@@ -14,7 +10,6 @@ module Numo
|
|
|
14
10
|
GAUSS61: Integer
|
|
15
11
|
COSINE: Integer
|
|
16
12
|
SINE: Integer
|
|
17
|
-
|
|
18
13
|
def self.qag: (
|
|
19
14
|
Numeric a,
|
|
20
15
|
Numeric b,
|
|
@@ -23,14 +18,12 @@ module Numo
|
|
|
23
18
|
?limit: Integer,
|
|
24
19
|
?key: Integer
|
|
25
20
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
26
|
-
|
|
27
21
|
def self.qng: (
|
|
28
22
|
Numeric a,
|
|
29
23
|
Numeric b,
|
|
30
24
|
?epsabs: Numeric,
|
|
31
25
|
?epsrel: Numeric
|
|
32
26
|
) { (Float) -> Numeric } -> [Float, Float, Integer]
|
|
33
|
-
|
|
34
27
|
def self.qags: (
|
|
35
28
|
Numeric a,
|
|
36
29
|
Numeric b,
|
|
@@ -38,34 +31,29 @@ module Numo
|
|
|
38
31
|
?epsrel: Numeric,
|
|
39
32
|
?limit: Integer
|
|
40
33
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
41
|
-
|
|
42
34
|
def self.qagp: (
|
|
43
35
|
Array[Numeric] points,
|
|
44
36
|
?epsabs: Numeric,
|
|
45
37
|
?epsrel: Numeric,
|
|
46
38
|
?limit: Integer
|
|
47
39
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
48
|
-
|
|
49
40
|
def self.qagi: (
|
|
50
41
|
?epsabs: Numeric,
|
|
51
42
|
?epsrel: Numeric,
|
|
52
43
|
?limit: Integer
|
|
53
44
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
54
|
-
|
|
55
45
|
def self.qagiu: (
|
|
56
46
|
Numeric a,
|
|
57
47
|
?epsabs: Numeric,
|
|
58
48
|
?epsrel: Numeric,
|
|
59
49
|
?limit: Integer
|
|
60
50
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
61
|
-
|
|
62
51
|
def self.qagil: (
|
|
63
52
|
Numeric b,
|
|
64
53
|
?epsabs: Numeric,
|
|
65
54
|
?epsrel: Numeric,
|
|
66
55
|
?limit: Integer
|
|
67
56
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
68
|
-
|
|
69
57
|
def self.qawc: (
|
|
70
58
|
Numeric a,
|
|
71
59
|
Numeric b,
|
|
@@ -74,7 +62,6 @@ module Numo
|
|
|
74
62
|
?epsrel: Numeric,
|
|
75
63
|
?limit: Integer
|
|
76
64
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
77
|
-
|
|
78
65
|
def self.qaws: (
|
|
79
66
|
Numeric a,
|
|
80
67
|
Numeric b,
|
|
@@ -86,7 +73,6 @@ module Numo
|
|
|
86
73
|
?epsrel: Numeric,
|
|
87
74
|
?limit: Integer
|
|
88
75
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
89
|
-
|
|
90
76
|
def self.qawo: (
|
|
91
77
|
Numeric a,
|
|
92
78
|
Numeric b,
|
|
@@ -96,7 +82,6 @@ module Numo
|
|
|
96
82
|
?epsrel: Numeric,
|
|
97
83
|
?limit: Integer
|
|
98
84
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
99
|
-
|
|
100
85
|
def self.qawf: (
|
|
101
86
|
Numeric a,
|
|
102
87
|
Numeric omega,
|
|
@@ -104,7 +89,6 @@ module Numo
|
|
|
104
89
|
?epsabs: Numeric,
|
|
105
90
|
?limit: Integer
|
|
106
91
|
) { (Float) -> Numeric } -> [Float, Float]
|
|
107
|
-
|
|
108
92
|
def self.cquad: (
|
|
109
93
|
Numeric a,
|
|
110
94
|
Numeric b,
|
|
@@ -112,7 +96,6 @@ module Numo
|
|
|
112
96
|
?epsrel: Numeric,
|
|
113
97
|
?limit: Integer
|
|
114
98
|
) { (Float) -> Numeric } -> [Float, Float, Integer]
|
|
115
|
-
|
|
116
99
|
def self.romberg: (
|
|
117
100
|
Numeric a,
|
|
118
101
|
Numeric b,
|
|
@@ -120,7 +103,6 @@ module Numo
|
|
|
120
103
|
?epsrel: Numeric,
|
|
121
104
|
?limit: Integer
|
|
122
105
|
) { (Float) -> Numeric } -> [Float, Integer]
|
|
123
|
-
|
|
124
106
|
def self.glfixed: (
|
|
125
107
|
Numeric a,
|
|
126
108
|
Numeric b,
|
data/sig/numo/gsl.rbs
CHANGED
metadata
CHANGED
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: numo-gsl-integration
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Takahiro SATOH
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
-
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: numo-gsl-alt
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - ">="
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.1.3
|
|
19
|
-
- - "<"
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: '0.2'
|
|
22
|
-
type: :runtime
|
|
23
|
-
prerelease: false
|
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
requirements:
|
|
26
|
-
- - ">="
|
|
27
|
-
- !ruby/object:Gem::Version
|
|
28
|
-
version: 0.1.3
|
|
29
|
-
- - "<"
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version: '0.2'
|
|
11
|
+
dependencies: []
|
|
32
12
|
description: Provides GNU Scientific Library numerical integration routines under
|
|
33
13
|
Numo::GSL::Integration.
|
|
34
14
|
email:
|