From 1b0e2b2a09d75b0b1502ff46c9f11ec5535d8abc Mon Sep 17 00:00:00 2001 From: Jaspe Michael Date: Sat, 23 Nov 2024 23:30:10 +0200 Subject: [PATCH 1/4] feat: Implementation of the mid-point and trapezoidal rule - Created the `.c` file - Added comments to make the code understandable --- numerical_methods/newton_cotes_formulas.c | 112 ++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 numerical_methods/newton_cotes_formulas.c diff --git a/numerical_methods/newton_cotes_formulas.c b/numerical_methods/newton_cotes_formulas.c new file mode 100644 index 0000000000..718977af3a --- /dev/null +++ b/numerical_methods/newton_cotes_formulas.c @@ -0,0 +1,112 @@ +#include +#include + +#define MAX_ITERATIONS 100 + +/* + + * @description: Newton-Cotes formulas are a group of formulas for numerical integration based on evaluating the integrand at equally spaced points. + + * @conventions: + - In this file, `a` and `b` represents the lower and upper bound, respectively. + - The integrand(function to integrate) is called 'f' + - All integrands take a double as an argument, even if no decimal numbers are provided or needed(for generalization purposes and precision) + + * @reference: For more information, consult https://en.wikipedia.org/wiki/Newton%E2%80%93Cotes_formulas + +*/ + + +/* + * @brief: Function that represents the function to integrate + * @args: Takes a double as an argument to generalize all values of the input + * @examples: f(x) = y, x is the input, y is the output +*/ +typedef double (*function)(double); + + +/* + + * @brief: Function that represents a method to solve an integral + * @args: + - function: Function to integrate + - An integer that represents the number of iterations to make when estimating the ssolution + - A double that represents the lower bound + - Another double that represents the upper bound + +*/ + +typedef double (*method)(function, int, double, double); + +// Functions representing all the solving methods implemented + +double trapezoid(function, int, double, double); +double mid_point_rule(function, int, double, double); + +// Example functions to integrate + +double f1(double x){ + return x*x; +} + +double f2(double x){ + return x*x*x; +} + +/* + * @brief: Function that generate an example for each solving method function + * @args: + - method: The function representing the method used + - method_name: The name of the method used + - f: function to integrate + - a: the lower bound + - b: the upper bound +*/ + +void example(method _method, const char* method_name, function f, double a, double b){ + printf("\nIntegral of the given function between %.3lf and %.3lf(%s method)\n", a, b, method_name); + printf("---------------\n"); + printf("With %d iterations: %lf\n", MAX_ITERATIONS, _method(f, MAX_ITERATIONS, a, b)); + printf("With %d iterations: %lf\n", MAX_ITERATIONS*2, _method(f, MAX_ITERATIONS*2, a, b)); + printf("---------------\n"); +} + +/* + * @brief: The main function + * @args: Takes no argument +*/ + +int main(void){ + int a, b; + printf("Integration bounds(separated by a space): "); + scanf("%d %d", &a, &b); + example(trapezoid, "trapezoid", f1, a, b); + example(mid_point_rule, "mid-point", f1, a, b); + return EXIT_SUCCESS; +} + +/* + The section below contains different methods to solve definite integrals +*/ + +// Closed methods section + +double trapezoid(function f, int n, double a, double b){ + double area=0.5*f(a)+0.5*f(b), h = (b-a)/n; + + for (int i=1; i Date: Sun, 24 Nov 2024 00:08:35 +0200 Subject: [PATCH 2/4] fix: Added simpsons rules --- numerical_methods/newton_cotes_formulas.c | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/numerical_methods/newton_cotes_formulas.c b/numerical_methods/newton_cotes_formulas.c index 718977af3a..4d5bd9c6e7 100644 --- a/numerical_methods/newton_cotes_formulas.c +++ b/numerical_methods/newton_cotes_formulas.c @@ -41,10 +41,16 @@ typedef double (*method)(function, int, double, double); // Functions representing all the solving methods implemented double trapezoid(function, int, double, double); +double simpson1_3(function, int, double, double); +double simpson3_8(function, int, double, double); double mid_point_rule(function, int, double, double); // Example functions to integrate +double f(double x){ + return x; +} + double f1(double x){ return x*x; } @@ -81,6 +87,8 @@ int main(void){ printf("Integration bounds(separated by a space): "); scanf("%d %d", &a, &b); example(trapezoid, "trapezoid", f1, a, b); + example(simpson1_3, "simpson 1/3", f1, a, b); + example(simpson1_3, "simpson 3/8", f1, a, b); example(mid_point_rule, "mid-point", f1, a, b); return EXIT_SUCCESS; } @@ -100,6 +108,24 @@ double trapezoid(function f, int n, double a, double b){ return area*h; } +// Simpson 1/3 +double simpson1_3(function f, int n, double a, double b){ + double area=f(a)+f(b), h = (b-a)/n; + + for (int i=1; i Date: Sun, 24 Nov 2024 00:08:52 +0200 Subject: [PATCH 3/4] feat: Added Boole's rule --- numerical_methods/newton_cotes_formulas.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/numerical_methods/newton_cotes_formulas.c b/numerical_methods/newton_cotes_formulas.c index 4d5bd9c6e7..242c81fd5e 100644 --- a/numerical_methods/newton_cotes_formulas.c +++ b/numerical_methods/newton_cotes_formulas.c @@ -44,6 +44,7 @@ double trapezoid(function, int, double, double); double simpson1_3(function, int, double, double); double simpson3_8(function, int, double, double); double mid_point_rule(function, int, double, double); +double boole(function, int, double, double); // Example functions to integrate @@ -90,6 +91,7 @@ int main(void){ example(simpson1_3, "simpson 1/3", f1, a, b); example(simpson1_3, "simpson 3/8", f1, a, b); example(mid_point_rule, "mid-point", f1, a, b); + example(boole, "boole", f1, a, b); return EXIT_SUCCESS; } @@ -126,6 +128,20 @@ double simpson3_8(function f, int n, double a, double b){ } return 3*(area*h)/8; } + +double boole(function f, int n, double a, double b){ + double area=7*(f(a)+f(b)), h = (b-a)/n; + + for (int i=1; i Date: Sun, 24 Nov 2024 01:36:44 +0200 Subject: [PATCH 4/4] feat: Added precise comments and essential macros - Added macros to select which function to integrate among the given ones(new can be added also) - Enhanced comments for the code to be quickly readable --- numerical_methods/newton_cotes_formulas.c | 105 ++++++++++++++++------ 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/numerical_methods/newton_cotes_formulas.c b/numerical_methods/newton_cotes_formulas.c index 242c81fd5e..634b864220 100644 --- a/numerical_methods/newton_cotes_formulas.c +++ b/numerical_methods/newton_cotes_formulas.c @@ -1,7 +1,6 @@ #include #include - -#define MAX_ITERATIONS 100 +#include /* @@ -17,9 +16,26 @@ */ +/* + * @brief: Compares 2 doubles + * @param d1 the first number of type double + * @param d2 the second number of type double + * @param p the precision + * return 1 if they are equal using the precision p, 0 otherwise +*/ + +#define COMPARE_DOUBLE(d1, d2, p) \ + (((d1 - p) < d2) && ((d1 + p) > d2)) ? 1 : 0 + +#define MAX_ITERATIONS 100 + +#define FUNCTION(n) f##n +#define EXPAND(x) FUNCTION(x) // Expand the given function_code to the corresponding function +#define DEFAULT 0 // the default function is f0, change this to use another function + /* * @brief: Function that represents the function to integrate - * @args: Takes a double as an argument to generalize all values of the input + * @param: Takes a double as a parameter to generalize all values of the input * @examples: f(x) = y, x is the input, y is the output */ typedef double (*function)(double); @@ -28,17 +44,20 @@ typedef double (*function)(double); /* * @brief: Function that represents a method to solve an integral - * @args: - - function: Function to integrate - - An integer that represents the number of iterations to make when estimating the ssolution - - A double that represents the lower bound - - Another double that represents the upper bound + * @params: + - function: Function to integrate + - An integer that represents the number of iterations to make when estimating the ssolution + - A double that represents the lower bound + - Another double that represents the upper bound */ typedef double (*method)(function, int, double, double); -// Functions representing all the solving methods implemented +/* + * @brief: All the integral-finding functions implemented + * @description: These functions follow the same syntax as `method` +*/ double trapezoid(function, int, double, double); double simpson1_3(function, int, double, double); @@ -46,23 +65,27 @@ double simpson3_8(function, int, double, double); double mid_point_rule(function, int, double, double); double boole(function, int, double, double); -// Example functions to integrate -double f(double x){ - return x; +/* + * Example functions to integrate +*/ + +double f0(double x){ + return x; // Linear function } double f1(double x){ - return x*x; + return x*x; // Quadratic function: x² } double f2(double x){ - return x*x*x; + return x*x*x; // Cubic function: x³ } + /* * @brief: Function that generate an example for each solving method function - * @args: + * @params: - method: The function representing the method used - method_name: The name of the method used - f: function to integrate @@ -78,27 +101,59 @@ void example(method _method, const char* method_name, function f, double a, doub printf("---------------\n"); } + /* - * @brief: The main function - * @args: Takes no argument + * @brief: Tests implementation + * @returns: nothing */ +void test(void){ + double result = 4.0, precision = 0.00001; + assert(COMPARE_DOUBLE(trapezoid(EXPAND(DEFAULT), MAX_ITERATIONS, 1, 3), result, precision) == 1); + assert(COMPARE_DOUBLE(simpson1_3(EXPAND(DEFAULT), MAX_ITERATIONS, 1, 3), result, precision) == 1); -int main(void){ + // The 3/8 rule can't find the integral with a linear function as the integrand + assert(COMPARE_DOUBLE(simpson3_8(EXPAND(DEFAULT), MAX_ITERATIONS, 1, 3), result, precision) == 0); + + assert(COMPARE_DOUBLE(mid_point_rule(EXPAND(DEFAULT), MAX_ITERATIONS, 1, 3), result, precision) == 1); + assert(COMPARE_DOUBLE(boole(EXPAND(DEFAULT), MAX_ITERATIONS, 1, 3), result, precision) == 1); + + printf("All tests ran successfully..."); +} + + +/* + * @brief: Function to allow the user to input values and test the script + * @returns: nothing +*/ + +void experimentation(void){ int a, b; printf("Integration bounds(separated by a space): "); scanf("%d %d", &a, &b); - example(trapezoid, "trapezoid", f1, a, b); - example(simpson1_3, "simpson 1/3", f1, a, b); - example(simpson1_3, "simpson 3/8", f1, a, b); - example(mid_point_rule, "mid-point", f1, a, b); - example(boole, "boole", f1, a, b); + example(trapezoid, "trapezoid", EXPAND(DEFAULT), a, b); + example(simpson1_3, "simpson 1/3", EXPAND(DEFAULT), a, b); + example(simpson1_3, "simpson 3/8", EXPAND(DEFAULT), a, b); + example(mid_point_rule, "mid-point", EXPAND(DEFAULT), a, b); + example(boole, "boole", EXPAND(DEFAULT), a, b); +} + +/* + * @brief: The main function + * @params: Takes no parameters + * @returns 0(EXIT_SUCCESS) if no error occured +*/ +int main(void){ + test(); // call experimentation() to test for yourself this script return EXIT_SUCCESS; } + /* The section below contains different methods to solve definite integrals + Check the @reference at the beginning of the file to learn more about them. */ + // Closed methods section double trapezoid(function f, int n, double a, double b){ @@ -110,7 +165,6 @@ double trapezoid(function f, int n, double a, double b){ return area*h; } -// Simpson 1/3 double simpson1_3(function f, int n, double a, double b){ double area=f(a)+f(b), h = (b-a)/n; @@ -142,7 +196,8 @@ double boole(function f, int n, double a, double b){ return 2*(area*h)/45; } -// Open methods section + +// Open method section double mid_point_rule(function f, int n, double a, double b){ double h = (b-a)/n;