TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
composite_simpson_rule.cpp File Reference

Implementation of the Composite Simpson Rule for the approximation. More...

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <map>
Include dependency graph for composite_simpson_rule.cpp:

Go to the source code of this file.

Namespaces

namespace  numerical_methods
 for assert
 
namespace  simpson_method
 Contains the Simpson's method implementation.
 

Functions

double numerical_methods::simpson_method::evaluate_by_simpson (std::int32_t N, double h, double a, const std::function< double(double)> &func)
 
double numerical_methods::simpson_method::f (double x)
 A function f(x) that will be used to test the method.
 
double numerical_methods::simpson_method::g (double x)
 Another test function.
 
double numerical_methods::simpson_method::k (double x)
 Another test function.
 
double numerical_methods::simpson_method::l (double x)
 Another test function.
 
static void test (std::int32_t N, double h, double a, double b, bool used_argv_parameters)
 Self-test implementations.
 
int main (int argc, char **argv)
 Main function.
 

Detailed Description

Implementation of the Composite Simpson Rule for the approximation.

The following is an implementation of the Composite Simpson Rule for the approximation of definite integrals. More info -> wiki: https://en.wikipedia.org/wiki/Simpson%27s_rule#Composite_Simpson's_rule

The idea is to split the interval in an EVEN number N of intervals and use as interpolation points the xi for which it applies that xi = x0 + i*h, where h is a step defined as h = (b-a)/N where a and b are the first and last points of the interval of the integration [a, b].

We create a table of the xi and their corresponding f(xi) values and we evaluate the integral by the formula: I = h/3 * {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)}

That means that the first and last indexed i f(xi) are multiplied by 1, the odd indexed f(xi) by 4 and the even by 2.

In this program there are 4 sample test functions f, g, k, l that are evaluated in the same interval.

Arguments can be passed as parameters from the command line argv[1] = N, argv[2] = a, argv[3] = b

N must be even number and a<b.

In the end of the main() i compare the program's result with the one from mathematical software with 2 decimal points margin.

Add sample function by replacing one of the f, g, k, l and the assert

Author
ggkogkou

Definition in file composite_simpson_rule.cpp.

Function Documentation

◆ evaluate_by_simpson()

double numerical_methods::simpson_method::evaluate_by_simpson ( std::int32_t N,
double h,
double a,
const std::function< double(double)> & func )

Definition at line 67 of file composite_simpson_rule.cpp.

68 {
69 std::map<std::int32_t, double>
70 data_table; // Contains the data points. key: i, value: f(xi)
71 double xi = a; // Initialize xi to the starting point x0 = a
72
73 // Create the data table
74 double temp = NAN;
75 for (std::int32_t i = 0; i <= N; i++) {
76 temp = func(xi);
77 data_table.insert(
78 std::pair<std::int32_t, double>(i, temp)); // add i and f(xi)
79 xi += h; // Get the next point xi for the next iteration
80 }
81
82 // Evaluate the integral.
83 // Remember: f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)
84 double evaluate_integral = 0;
85 for (std::int32_t i = 0; i <= N; i++) {
86 if (i == 0 || i == N) {
87 evaluate_integral += data_table.at(i);
88 } else if (i % 2 == 1) {
89 evaluate_integral += 4 * data_table.at(i);
90 } else {
91 evaluate_integral += 2 * data_table.at(i);
92 }
93 }
94
95 // Multiply by the coefficient h/3
96 evaluate_integral *= h / 3;
97
98 // If the result calculated is nan, then the user has given wrong input
99 // interval.
100 assert(!std::isnan(evaluate_integral) &&
101 "The definite integral can't be evaluated. Check the validity of "
102 "your input.\n");
103 // Else return
104 return evaluate_integral;
105}
int h(int key)
constexpr uint32_t N
A struct to represent sparse table for min() as their invariant function, for the given array A....

◆ f()

double numerical_methods::simpson_method::f ( double x)

A function f(x) that will be used to test the method.

Parameters
xThe independent variable xi
Returns
the value of the dependent variable yi = f(xi)

Definition at line 113 of file composite_simpson_rule.cpp.

113{ return std::sqrt(x) + std::log(x); }

◆ g()

double numerical_methods::simpson_method::g ( double x)

Another test function.

Definition at line 115 of file composite_simpson_rule.cpp.

115{ return std::exp(-x) * (4 - std::pow(x, 2)); }

◆ k()

double numerical_methods::simpson_method::k ( double x)

Another test function.

Definition at line 117 of file composite_simpson_rule.cpp.

117{ return std::sqrt(2 * std::pow(x, 3) + 3); }

◆ l()

double numerical_methods::simpson_method::l ( double x)

Another test function.

Definition at line 119 of file composite_simpson_rule.cpp.

119{ return x + std::log(2 * x + 1); }

◆ main()

int main ( int argc,
char ** argv )

Main function.

Parameters
argccommandline argument count (ignored)
argvcommandline array of arguments (ignored)
Returns
0 on exit

Number of intervals to divide the integration interval. MUST BE EVEN

Starting and ending point of the integration in the real axis

Step, calculated by a, b and N

Definition at line 170 of file composite_simpson_rule.cpp.

170 {
171 std::int32_t N = 16;
173 double a = 1, b = 3;
175 double h = NAN;
176
177 bool used_argv_parameters =
178 false; // If argv parameters are used then the assert must be omitted
179 // for the tst cases
180
181 // Get user input (by the command line parameters or the console after
182 // displaying messages)
183 if (argc == 4) {
184 N = std::atoi(argv[1]);
185 a = std::atof(argv[2]);
186 b = std::atof(argv[3]);
187 // Check if a<b else abort
188 assert(a < b && "a has to be less than b");
189 assert(N > 0 && "N has to be > 0");
190 if (N < 16 || a != 1 || b != 3) {
191 used_argv_parameters = true;
192 }
193 std::cout << "You selected N=" << N << ", a=" << a << ", b=" << b
194 << std::endl;
195 } else {
196 std::cout << "Default N=" << N << ", a=" << a << ", b=" << b
197 << std::endl;
198 }
199
200 // Find the step
201 h = (b - a) / N;
202
203 test(N, h, a, b, used_argv_parameters); // run self-test implementations
204
205 return 0;
206}
static void test()
Self-test implementations.

◆ test()

static void test ( std::int32_t N,
double h,
double a,
double b,
bool used_argv_parameters )
static

Self-test implementations.

Parameters
Nis the number of intervals
his the step
ais x0
bis the end of the interval
used_argv_parametersis 'true' if argv parameters are given and 'false' if not

Definition at line 132 of file composite_simpson_rule.cpp.

133 {
134 // Call the functions and find the integral of each function
135 double result_f = numerical_methods::simpson_method::evaluate_by_simpson(
136 N, h, a, numerical_methods::simpson_method::f);
137 assert((used_argv_parameters || (result_f >= 4.09 && result_f <= 4.10)) &&
138 "The result of f(x) is wrong");
139 std::cout << "The result of integral f(x) on interval [" << a << ", " << b
140 << "] is equal to: " << result_f << std::endl;
141
142 double result_g = numerical_methods::simpson_method::evaluate_by_simpson(
143 N, h, a, numerical_methods::simpson_method::g);
144 assert((used_argv_parameters || (result_g >= 0.27 && result_g <= 0.28)) &&
145 "The result of g(x) is wrong");
146 std::cout << "The result of integral g(x) on interval [" << a << ", " << b
147 << "] is equal to: " << result_g << std::endl;
148
149 double result_k = numerical_methods::simpson_method::evaluate_by_simpson(
150 N, h, a, numerical_methods::simpson_method::k);
151 assert((used_argv_parameters || (result_k >= 9.06 && result_k <= 9.07)) &&
152 "The result of k(x) is wrong");
153 std::cout << "The result of integral k(x) on interval [" << a << ", " << b
154 << "] is equal to: " << result_k << std::endl;
155
156 double result_l = numerical_methods::simpson_method::evaluate_by_simpson(
157 N, h, a, numerical_methods::simpson_method::l);
158 assert((used_argv_parameters || (result_l >= 7.16 && result_l <= 7.17)) &&
159 "The result of l(x) is wrong");
160 std::cout << "The result of integral l(x) on interval [" << a << ", " << b
161 << "] is equal to: " << result_l << std::endl;
162}