SDDSlib
Loading...
Searching...
No Matches
qromb.c
Go to the documentation of this file.
1/**
2 * @file qromb.c
3 * @brief Performs numerical integration using Romberg's method.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author H. Shang, R. Soliday
14 */
15/*
16 converted by shang from http://netlib.org/toms/351
17*/
18#include "mdb.h"
19
20/**
21 * @brief Computes the definite integral of a function using Romberg's method.
22 *
23 * Estimates the integral of the function \p func over the interval \f$ [a, b] \f$ using Romberg's
24 * numerical integration technique, which applies Richardson extrapolation to the trapezoidal rule
25 * to achieve higher accuracy.
26 *
27 * @param func Pointer to the function to integrate. The function should accept a single \c double argument and return a \c double.
28 * @param maxe Maximum number of extrapolation steps to perform.
29 * @param a Lower limit of integration.
30 * @param b Upper limit of integration.
31 * @param eps Desired accuracy (error tolerance) for the integral approximation.
32 * @return The estimated value of the integral. Returns 0 if the maximum number of steps is exceeded without achieving the desired accuracy.
33 */
34double qromb(double (*func)(), /* pointer to function*/
35 long maxe,
36 double a, double b, /* upper, lower limits of integeration*/
37 double eps /*error */) {
38 double T, R, BB, S, H, S1, S0, err, result;
39 static long MAXE = 0;
40 static double *RM = NULL;
41 long K, K1, N, N0, N1, KK, KKK, K0, J, L, K2;
42
43 T = (b - a) * (func(a) + func(b)) * .5; /* initial trapzoid rule */
44 if (RM == NULL || maxe > MAXE) {
45 if (RM)
46 free(RM);
47 RM = malloc(sizeof(*RM) * (maxe + 2));
48 MAXE = maxe;
49 }
50 RM[1] = (b - a) * func((a + b) * 0.5);
51 N = 2;
52 R = 4.0;
53
54 for (K = 1; K <= maxe; K++) {
55 BB = (R * 0.5 - 1.0) / (R - 1.0);
56 /*improved trapzoid value */
57 T = RM[1] + BB * (T - RM[1]);
58 /* double number of subdivision of a and b */
59 N = 2 * N;
60 S = 0;
61 H = (b - a) / (N * 1.0);
62 /* calculate rectangle value */
63 if (N <= 32) {
64 N0 = N1 = N;
65 } else if (N <= 512) {
66 N0 = 32;
67 N1 = N;
68 } else {
69 N0 = 32;
70 N1 = 512;
71 }
72 for (K2 = 1; K2 <= N; K2 += 512) {
73 S1 = 0.0;
74 KK = K2 + N1 - 1;
75 for (K1 = K2; K1 <= KK; K1 += 32) {
76 S0 = 0.0;
77 KKK = K1 + N0 - 1;
78 for (K0 = K1; K0 <= KKK; K0 += 2)
79 S0 += func(a + K0 * H);
80 S1 += S0;
81 }
82 S += S1;
83 }
84 RM[K + 1] = 2.0 * H * S;
85 /* end of calculate rectangle value */
86 R = 4.0;
87 for (J = 1; J <= K; J++) {
88 L = K + 1 - J;
89 RM[L] = RM[L + 1] + (RM[L + 1] - RM[L]) / (R - 1.0);
90 R = 4.0 * R;
91 }
92 err = fabs(T - RM[1]) * 0.5;
93 if (err <= eps) {
94 K = 0;
95 result = (T + RM[1]) * 0.5;
96 N = N + 1;
97 return result;
98 }
99 }
100 fprintf(stderr, "too many qrom steps\n");
101 return 0;
102}
double qromb(double(*func)(), long maxe, double a, double b, double eps)
Computes the definite integral of a function using Romberg's method.
Definition qromb.c:34