Algorithms_in_C++ 1.0.0
Set of algorithms implemented in C++.
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:

Namespaces

namespace  numerical_methods
 for IO operations
 
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, 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. More...
 
double numerical_methods::simpson_method::g (double x)
 Another test function. More...
 
double numerical_methods::simpson_method::k (double x)
 Another test function. More...
 
double numerical_methods::simpson_method::l (double x)
 Another test function. More...
 
static void test (std::int32_t N, double h, double a, double b, bool used_argv_parameters)
 Self-test implementations. More...
 
int main (int argc, char **argv)
 Main function. More...
 

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

Function Documentation

◆ evaluate_by_simpson()

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

◆ 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)
111{ return std::sqrt(x) + std::log(x); }
T log(T... args)
T sqrt(T... args)
Here is the call graph for this function:

◆ g()

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

Another test function.

113{ return std::exp(-x) * (4 - std::pow(x, 2)); }
T exp(T... args)
T pow(T... args)
Here is the call graph for this function:

◆ k()

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

Another test function.

Examples
/Users/runner/work/C-Plus-Plus/C-Plus-Plus/numerical_methods/rungekutta.cpp.
115{ return std::sqrt(2 * std::pow(x, 3) + 3); }
Here is the call graph for this function:

◆ l()

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

Another test function.

117{ return x + std::log(2 * x + 1); }
Here is the call graph for this function:

◆ 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

168 {
169 std::int32_t N = 16; /// Number of intervals to divide the integration
170 /// interval. MUST BE EVEN
171 double a = 1, b = 3; /// Starting and ending point of the integration in
172 /// the real axis
173 double h; /// Step, calculated by a, b and N
174
175 bool used_argv_parameters =
176 false; // If argv parameters are used then the assert must be omitted
177 // for the tst cases
178
179 // Get user input (by the command line parameters or the console after
180 // displaying messages)
181 if (argc == 4) {
182 N = std::atoi(argv[1]);
183 a = (double)std::atof(argv[2]);
184 b = (double)std::atof(argv[3]);
185 // Check if a<b else abort
186 assert(a < b && "a has to be less than b");
187 assert(N > 0 && "N has to be > 0");
188 if (N < 16 || a != 1 || b != 3)
189 used_argv_parameters = true;
190 std::cout << "You selected N=" << N << ", a=" << a << ", b=" << b
191 << std::endl;
192 } else
193 std::cout << "Default N=" << N << ", a=" << a << ", b=" << b
194 << std::endl;
195
196 // Find the step
197 h = (b - a) / N;
198
199 test(N, h, a, b, used_argv_parameters); // run self-test implementations
200
201 return 0;
202}
T atof(T... args)
T atoi(T... args)
static void test(std::int32_t N, double h, double a, double b, bool used_argv_parameters)
Self-test implementations.
Definition: composite_simpson_rule.cpp:130
T endl(T... args)
Here is the call graph for this function:

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