5#ifndef LINE_API_QSYS_QUADRATURE_H
6#define LINE_API_QSYS_QUADRATURE_H
54const std::vector<T>& gk15_nodes() {
55 static const std::vector<T> x = {
56 num_traits<T>::from_double(0.991455371120812639206854697526329),
57 num_traits<T>::from_double(0.949107912342758524526189684047851),
58 num_traits<T>::from_double(0.864864423359769072789712788640926),
59 num_traits<T>::from_double(0.741531185599394439863864773280788),
60 num_traits<T>::from_double(0.586087235467691130294144838258730),
61 num_traits<T>::from_double(0.405845151377397166906606412076961),
62 num_traits<T>::from_double(0.207784955007898467600689403773245),
63 num_traits<T>::from_double(0.0)};
69const std::vector<T>& gk15_weights() {
70 static const std::vector<T> w = {
71 num_traits<T>::from_double(0.022935322010529224963732008058970),
72 num_traits<T>::from_double(0.063092092629978553290700663189204),
73 num_traits<T>::from_double(0.104790010322250183839876322541518),
74 num_traits<T>::from_double(0.140653259715525918745189590510238),
75 num_traits<T>::from_double(0.169004726639267902826583426598550),
76 num_traits<T>::from_double(0.190350578064785409913256402421014),
77 num_traits<T>::from_double(0.204432940075298892414161999234649),
78 num_traits<T>::from_double(0.209482141084727828012999174891714)};
84const std::vector<T>& g7_weights() {
85 static const std::vector<T> w = {
86 num_traits<T>::from_double(0.129484966168869693270611432679082),
87 num_traits<T>::from_double(0.279705391489276667901467771423780),
88 num_traits<T>::from_double(0.381830050505118944950369775488975),
89 num_traits<T>::from_double(0.417959183673469387755102040816327)};
97template <
class T,
class F>
98T gk15_panel(F&& f,
const T& a,
const T& b, T& err) {
99 const T two = num_traits<T>::from_int(2);
100 const T c = (a + b) / two;
101 const T h = (b - a) / two;
102 const std::vector<T>& x = gk15_nodes<T>();
103 const std::vector<T>& wk = gk15_weights<T>();
104 const std::vector<T>& wg = g7_weights<T>();
106 T K = num_traits<T>::from_int(0);
107 T G = num_traits<T>::from_int(0);
108 for (std::size_t i = 0; i < 7; ++i) {
109 const T d = h * x[i];
110 const T fsum = f(T(c - d)) + f(T(c + d));
112 if (i % 2 == 1) G += wg[i / 2] * fsum;
132template <
class T,
class F>
133T gk15_adapt(F&& f,
const T& a,
const T& b,
const T& reltol,
const T& abstol,
unsigned depth,
134 unsigned min_depth) {
135 T err = num_traits<T>::from_int(0);
136 const T q = gk15_panel(f, a, b, err);
137 const T target = reltol *
num_abs(q);
138 if (min_depth == 0 && (depth == 0 || err <= (target > abstol ? target : abstol)))
return q;
139 if (depth == 0)
return q;
140 const T m = (a + b) / num_traits<T>::from_int(2);
141 const T half = abstol / num_traits<T>::from_int(2);
142 const unsigned md = min_depth == 0 ? 0u : min_depth - 1;
143 return gk15_adapt(f, a, m, reltol, half, depth - 1, md) +
144 gk15_adapt(f, m, b, reltol, half, depth - 1, md);
164template <
class T,
class F>
165T num_integral(F&& f,
const T& a,
const T& b,
const T& reltol,
const T& abstol,
166 unsigned depth = 50u,
unsigned init_panels = 8u,
unsigned min_depth = 3u) {
167 static_assert(num_traits<T>::has_transcendental,
168 "num_integral requires transcendental arithmetic");
169 if (b == a)
return num_traits<T>::from_int(0);
170 if (init_panels == 0) init_panels = 1;
171 const T np = num_traits<T>::from_int(
static_cast<long>(init_panels));
172 const T panel_abstol = abstol / np;
173 T total = num_traits<T>::from_int(0);
174 for (
unsigned i = 0; i < init_panels; ++i) {
175 const T lo = a + (b - a) * num_traits<T>::from_int(
static_cast<long>(i)) / np;
176 const T hi = a + (b - a) * num_traits<T>::from_int(
static_cast<long>(i + 1)) / np;
177 total += gk15_adapt(f, lo, hi, reltol, panel_abstol, depth, min_depth);
186T num_trapz(
const std::vector<T>& x,
const std::vector<T>& y) {
187 static_assert(num_traits<T>::has_transcendental,
188 "num_trapz requires transcendental arithmetic");
189 if (x.size() != y.size())
throw InputError(
"num_trapz: x and y have different lengths");
190 const T two = num_traits<T>::from_int(2);
191 T s = num_traits<T>::from_int(0);
192 for (std::size_t i = 1; i < x.size(); ++i) s += (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / two;
201std::vector<T> num_cumtrapz(
const std::vector<T>& x,
const std::vector<T>& y) {
202 static_assert(num_traits<T>::has_transcendental,
203 "num_cumtrapz requires transcendental arithmetic");
204 if (x.size() != y.size())
throw InputError(
"num_cumtrapz: x and y have different lengths");
205 const T two = num_traits<T>::from_int(2);
206 std::vector<T> c(x.size(), num_traits<T>::from_int(0));
207 for (std::size_t i = 1; i < x.size(); ++i)
208 c[i] = c[i - 1] + (x[i] - x[i - 1]) * (y[i] + y[i - 1]) / two;
The exception types the port throws.
Number-type abstraction for the templated API port.