12 typedef mpfr::mpreal Real;
13 typedef const mpfr::mpreal & Real_t;
28 void legendre_zeros();
29 void chebyshev_coefs();
30 void gauss_kronrod_abscissae();
31 void gauss_kronrod_weights();
33 Real legendre_err(
int deg, Real_t x, Real& err);
34 Real legendre_deriv(
int deg, Real_t x);
35 Real chebyshev_series(Real_t x, Real& err);
36 Real chebyshev_series_deriv(Real_t x);
39 GaussKronrod(
size_t m = 10);
41 size_t size() {
return n_; };
42 Real xgk(
int k) {
return (0 <= k && k < n_) ? xgk_[k] : Real(0); }
43 Real wgk(
int k) {
return (0 <= k && k < n_) ? wgk_[k] : Real(0); }
44 Real wg(
int k) {
return (0 <= k && k < n_/2) ? wg_[k] : Real(0); }
47 GaussKronrod::GaussKronrod(
size_t m) {
51 wg_ =
new Real[n_ / 2];
53 coefs =
new Real[n_ + 1];
54 zeros =
new Real[m_ + 2];
58 gauss_kronrod_abscissae();
59 gauss_kronrod_weights();
62 GaussKronrod::~GaussKronrod() {
70 void GaussKronrod::legendre_zeros() {
71 Real* temp =
new Real[m_+1];
76 for (
int k = 1; k <= m_; ++k) {
78 for (
int j = 0; j < k; ++j) {
82 Real x_j = (zeros[j] + zeros[j+1]) / 2;
83 Real P_k = legendre_err(k, x_j, epsilon);
84 while (abs(P_k) > epsilon && abs(delta) > mpfr::machine_epsilon()) {
85 delta = P_k / legendre_deriv(k, x_j);
87 P_k = legendre_err(k, x_j, epsilon);
93 zeros[k+1] = zeros[k];
94 for (
int j = 0; j < k; ++j) zeros[j+1] = temp[j];
99 void GaussKronrod::chebyshev_coefs() {
100 size_t ell = (m_ + 1)/2;
101 Real* alpha =
new Real[ell+1];
102 Real* f =
new Real[ell+1];
108 f[1] = Real(m_+1)/Real(2*m_ + 3);
112 for (
int k = 2; k <= ell; ++k) {
113 f[k] = f[k-1] * (2*k - 1) * (m_ + k) / (k * (2*m_ + 2*k + 1));
115 for (
int i = 1; i < k; ++i) alpha[k] -= f[i] * alpha[k-i];
118 for (
int k = 0; k <= ell; ++k) {
119 coefs[m_ + 1 - 2*k] = alpha[k];
120 if (m_ >= 2*k) coefs[m_ - 2*k] = Real(0);
127 void GaussKronrod::gauss_kronrod_weights() {
130 for (
int k = 0; k < n_ / 2; ++k) {
131 Real x = xgk_[2*k + 1];
132 wg_[k] = (Real(-2) / ((m_ + 1) * legendre_deriv(m_, x) * legendre_err(m_+1, x, err)));
138 Real F_m = Real(2) / Real(2*m_ + 1);
139 for (
int k = 1; k <= m_; ++k) F_m *= (Real(2*k) / Real(2*k - 1));
142 for (
size_t k = 0; k < n_; ++k) {
145 wgk_[k] = F_m / (legendre_err(m_, x, err) * chebyshev_series_deriv(x));
147 wgk_[k] = (wg_[k/2] + F_m / (legendre_deriv(m_, x) * chebyshev_series(x, err)));
152 void GaussKronrod::gauss_kronrod_abscissae() {
155 for (
int k = 0; 2*k < n_; ++k) {
158 Real x_k = (zeros[m_-k] + zeros[m_+1-k])/Real(2);
159 Real E = chebyshev_series(x_k, epsilon);
160 while (abs(E) > epsilon && abs(delta) > mpfr::machine_epsilon()) {
161 delta = E / chebyshev_series_deriv(x_k);
163 E = chebyshev_series(x_k, epsilon);
167 if (2*k+1 < n_) xgk_[2*k+1] = zeros[m_-k];
171 Real GaussKronrod::legendre_err(
int n, Real_t x, Real& err) {
181 Real P0 = Real(1), P1 = x, P2;
182 Real E0 = mpfr::machine_epsilon();
183 Real E1 = abs(x) * mpfr::machine_epsilon();
184 for (
int k = 1; k < n; ++k) {
185 P2 = ((2*k + 1) * x * P1 - k * P0) / (k + 1);
186 err = ((2*k + 1) * abs(x) * E1 + k * E0) / (2*(k + 1));
193 Real GaussKronrod::legendre_deriv(
int n, Real_t x) {
194 if (n == 0)
return Real(0);
195 else if (n == 1)
return Real(1);
197 Real P0 = Real(1), P1 = x, P2;
198 Real dP0 = Real(0), dP1 = Real(1), dP2;
199 for (
int k = 1; k < n; ++k) {
200 P2 = ((2*k + 1) * x * P1 - k * P0) / (k + Real(1));
201 dP2 = (2*k + 1) * P1 + dP0;
203 dP0 = dP1; dP1 = dP2;
208 Real GaussKronrod::chebyshev_series(Real_t x, Real& err) {
210 Real absc = abs(coefs[0]);
213 for (
int k = n_; k >= 1; --k) {
215 d1 = y2 * d1 - d2 + coefs[k];
217 absc += abs(coefs[k]);
220 err = absc * mpfr::machine_epsilon();
221 return x * d1 - d2 + coefs[0]/2;
224 Real GaussKronrod::chebyshev_series_deriv(Real_t x) {
228 for (
int k = n_; k >= 2; --k) {
230 d1 = y2 * d1 - d2 + k * coefs[k];
234 return y2 * d1 - d2 + coefs[1];