From f91bf7c2403840b71ea9d192dc4cfec573cfb77f Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Thu, 16 Mar 2023 01:21:59 +0900 Subject: [PATCH 01/14] feat: add bisection method --- numerical_methods/bisection_method.c | 100 +++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 numerical_methods/bisection_method.c diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c new file mode 100644 index 0000000000..4d62b2cae7 --- /dev/null +++ b/numerical_methods/bisection_method.c @@ -0,0 +1,100 @@ +/** + * @file + * @brief In mathematics, the bisection method is a root-finding method that + * applies to any continuous function for which one knows two values with + * opposite signs. https://en.wikipedia.org/wiki/Bisection_method + * @details + * The method consists of repeatedly bisecting the interval + * defined by these values and then selecting the subinterval in which the + * function changes sign, and therefore must contain a root. It is a very + * simple and robust method, but it is also relatively slow. Because of this, + * it is often used to obtain a rough approximation to a solution which is + * then used as a starting point for more rapidly converging methods. + * @author [Aybars Nazlica](https://github.com/aybarsnazlica) + */ + +#include /// for assert +#include /// for pow and fabs + +#define EPSILON 0.0001 // a small positive infinitesimal quantity +#define NMAX 50 // maximum number of iterations + +/** + * @brief Function documentation + * @param a First value + * @param b Second value + * @returns `sign` + */ +float sign(float a, float b) { return a * b; } + +/** + * @brief Polynomial function for root finding + * @param x + * @returns `function evaluation result` + */ +float func(float x) +{ + return pow(x, 3.0) + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10 +} + +/** + * @brief Function documentation + * @param x_left Lower interval value + * @param x_right Upper interval value + * @param tolerance error threshold + * @returns `root of the function` if bisection method succeed within the + * maximum number of iterations + * @returns `-1` if bisection method fails + */ +float bisection(float x_left, float x_right, float tolerance) +{ + int n = 1; // step counter + float middle; // midpoint + + while (n <= NMAX) + { + middle = (x_left + x_right) / 2; // bisect the interval + float error = fabs(x_left - x_right) / 2; + + if (func(middle) == 0.0 || error < tolerance) + { + return middle; + } + + if (sign(func(middle), func(x_left)) >= 0.0) + { + x_left = middle; // new lower interval + } + else + { + x_right = middle; // new upper interval + } + + n++; // increase step counter + } + return -1.0; // method failed (maximum number of steps exceeded) +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + /* Compares root value that is found by the bisection method within a given + * floating point error*/ + assert(fabs(bisection(1.0, 2.0, 0.0001) - 1.847473) <= + EPSILON); // the algorithm works as expected + assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) <= + EPSILON); // the algorithm works as expected +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} From 71f78a30d6449e0d0c45d3ed6be5b68a571e0e74 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Thu, 16 Mar 2023 01:34:39 +0900 Subject: [PATCH 02/14] fix function documentation --- numerical_methods/bisection_method.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 4d62b2cae7..26c58b1399 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -20,7 +20,7 @@ #define NMAX 50 // maximum number of iterations /** - * @brief Function documentation + * @brief Function to check if two values have the same sign * @param a First value * @param b Second value * @returns `sign` @@ -38,7 +38,7 @@ float func(float x) } /** - * @brief Function documentation + * @brief Root-finding method for a continuous function * @param x_left Lower interval value * @param x_right Upper interval value * @param tolerance error threshold From 527bc673a07d9577beb2aace10769bec11e5b43c Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 01:01:40 +0900 Subject: [PATCH 03/14] fix float to zero comparison --- numerical_methods/bisection_method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 26c58b1399..583ead0328 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -56,7 +56,7 @@ float bisection(float x_left, float x_right, float tolerance) middle = (x_left + x_right) / 2; // bisect the interval float error = fabs(x_left - x_right) / 2; - if (func(middle) == 0.0 || error < tolerance) + if (fabs(func(middle)) <= EPSILON || error < tolerance) { return middle; } From 395765124c1390d9523dd0babba6e08f0ec4253c Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 09:21:00 +0900 Subject: [PATCH 04/14] fix error definition --- numerical_methods/bisection_method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 583ead0328..1fdf270f22 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -54,7 +54,7 @@ float bisection(float x_left, float x_right, float tolerance) while (n <= NMAX) { middle = (x_left + x_right) / 2; // bisect the interval - float error = fabs(x_left - x_right) / 2; + float error = middle - x_left; if (fabs(func(middle)) <= EPSILON || error < tolerance) { From d3add48fd7d0c73d6378efd260d07cf66cf46df7 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 10:51:48 +0900 Subject: [PATCH 05/14] fix the sign function Co-authored-by: Sharon "Cass" Cassidy <122662061+CascadingCascade@users.noreply.github.com> --- numerical_methods/bisection_method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 1fdf270f22..995060458d 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -25,7 +25,7 @@ * @param b Second value * @returns `sign` */ -float sign(float a, float b) { return a * b; } +float sign(float a, float b) { return (a > 0 && b > 0) + (a < 0 && b < 0) - (a > 0 && b < 0) - (a < 0 && b > 0); } /** * @brief Polynomial function for root finding From cd05d6a915e1b1a8aa43eb3ec028778c4690977b Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 10:57:22 +0900 Subject: [PATCH 06/14] change float type to double type --- numerical_methods/bisection_method.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 995060458d..defea2f5f6 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -25,14 +25,18 @@ * @param b Second value * @returns `sign` */ -float sign(float a, float b) { return (a > 0 && b > 0) + (a < 0 && b < 0) - (a > 0 && b < 0) - (a < 0 && b > 0); } +double sign(double a, double b) +{ + return (a > 0 && b > 0) + (a < 0 && b < 0) - (a > 0 && b < 0) - + (a < 0 && b > 0); +} /** * @brief Polynomial function for root finding * @param x * @returns `function evaluation result` */ -float func(float x) +double func(double x) { return pow(x, 3.0) + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10 } @@ -46,15 +50,15 @@ float func(float x) * maximum number of iterations * @returns `-1` if bisection method fails */ -float bisection(float x_left, float x_right, float tolerance) +double bisection(double x_left, double x_right, double tolerance) { - int n = 1; // step counter - float middle; // midpoint + int n = 1; // step counter + double middle; // midpoint while (n <= NMAX) { middle = (x_left + x_right) / 2; // bisect the interval - float error = middle - x_left; + double error = middle - x_left; if (fabs(func(middle)) <= EPSILON || error < tolerance) { @@ -72,7 +76,7 @@ float bisection(float x_left, float x_right, float tolerance) n++; // increase step counter } - return -1.0; // method failed (maximum number of steps exceeded) + return -1; // method failed (maximum number of steps exceeded) } /** From 191d9c988ef2f4a3a8bee2853fc91329bf59cefd Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 11:00:44 +0900 Subject: [PATCH 07/14] fix sign comparison equals to zero --- numerical_methods/bisection_method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index defea2f5f6..525151d49e 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -65,7 +65,7 @@ double bisection(double x_left, double x_right, double tolerance) return middle; } - if (sign(func(middle), func(x_left)) >= 0.0) + if (sign(func(middle), func(x_left)) > 0.0) { x_left = middle; // new lower interval } From 9dbc983c94199c288af8570968d1909798871319 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Fri, 17 Mar 2023 11:11:56 +0900 Subject: [PATCH 08/14] remove pow function --- numerical_methods/bisection_method.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 525151d49e..366e7b7ca5 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -14,7 +14,7 @@ */ #include /// for assert -#include /// for pow and fabs +#include /// for fabs #define EPSILON 0.0001 // a small positive infinitesimal quantity #define NMAX 50 // maximum number of iterations @@ -38,7 +38,7 @@ double sign(double a, double b) */ double func(double x) { - return pow(x, 3.0) + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10 + return x * x * x + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10 } /** @@ -60,7 +60,7 @@ double bisection(double x_left, double x_right, double tolerance) middle = (x_left + x_right) / 2; // bisect the interval double error = middle - x_left; - if (fabs(func(middle)) <= EPSILON || error < tolerance) + if (fabs(func(middle)) < EPSILON || error < tolerance) { return middle; } @@ -87,9 +87,9 @@ static void test() { /* Compares root value that is found by the bisection method within a given * floating point error*/ - assert(fabs(bisection(1.0, 2.0, 0.0001) - 1.847473) <= + assert(fabs(bisection(1.0, 2.0, 0.0001) - 1.847473) < EPSILON); // the algorithm works as expected - assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) <= + assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) < EPSILON); // the algorithm works as expected } From 87eb303d786616f3921a0804347d1c372a57e48d Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sat, 18 Mar 2023 11:55:55 +0900 Subject: [PATCH 09/14] Update numerical_methods/bisection_method.c Co-authored-by: David Leal --- numerical_methods/bisection_method.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 366e7b7ca5..bb0ada22c1 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -1,8 +1,8 @@ /** * @file - * @brief In mathematics, the bisection method is a root-finding method that + * @brief In mathematics, the [Bisection Method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding method that * applies to any continuous function for which one knows two values with - * opposite signs. https://en.wikipedia.org/wiki/Bisection_method + * opposite signs. * @details * The method consists of repeatedly bisecting the interval * defined by these values and then selecting the subinterval in which the From 601e7faeaf0f8cfde7edbfbdbcd5b94ca71f0d2d Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sat, 18 Mar 2023 12:12:51 +0900 Subject: [PATCH 10/14] add parameter docs --- numerical_methods/bisection_method.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index bb0ada22c1..513d9a8363 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -1,8 +1,9 @@ /** * @file - * @brief In mathematics, the [Bisection Method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding method that - * applies to any continuous function for which one knows two values with - * opposite signs. + * @brief In mathematics, the [Bisection + * Method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding + * method that applies to any continuous function for which one knows two values + * with opposite signs. * @details * The method consists of repeatedly bisecting the interval * defined by these values and then selecting the subinterval in which the @@ -33,7 +34,7 @@ double sign(double a, double b) /** * @brief Polynomial function for root finding - * @param x + * @param x Input value (an element of the function's domain) * @returns `function evaluation result` */ double func(double x) @@ -45,7 +46,7 @@ double func(double x) * @brief Root-finding method for a continuous function * @param x_left Lower interval value * @param x_right Upper interval value - * @param tolerance error threshold + * @param tolerance Error threshold * @returns `root of the function` if bisection method succeed within the * maximum number of iterations * @returns `-1` if bisection method fails From eeda70ea027de5b6a7dd97c0431c7f8aadb3c060 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sun, 19 Mar 2023 00:15:51 +0900 Subject: [PATCH 11/14] update docs --- numerical_methods/bisection_method.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 513d9a8363..78a349b2ff 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -6,7 +6,7 @@ * with opposite signs. * @details * The method consists of repeatedly bisecting the interval - * defined by these values and then selecting the subinterval in which the + * defined by the two values and then selecting the subinterval in which the * function changes sign, and therefore must contain a root. It is a very * simple and robust method, but it is also relatively slow. Because of this, * it is often used to obtain a rough approximation to a solution which is @@ -33,8 +33,8 @@ double sign(double a, double b) } /** - * @brief Polynomial function for root finding - * @param x Input value (an element of the function's domain) + * @brief Continuous function for root-finding + * @param x Real input variable * @returns `function evaluation result` */ double func(double x) @@ -43,9 +43,10 @@ double func(double x) } /** - * @brief Root-finding method for a continuous function - * @param x_left Lower interval value - * @param x_right Upper interval value + * @brief Root-finding method for a continuous function given two values with + * opposite signs + * @param x_left Lower endpoint value of the interval + * @param x_right Upper endpoint value of the interval * @param tolerance Error threshold * @returns `root of the function` if bisection method succeed within the * maximum number of iterations @@ -68,11 +69,11 @@ double bisection(double x_left, double x_right, double tolerance) if (sign(func(middle), func(x_left)) > 0.0) { - x_left = middle; // new lower interval + x_left = middle; // new lower endpoint } else { - x_right = middle; // new upper interval + x_right = middle; // new upper endpoint } n++; // increase step counter From d88cfb9527c36ad2aaa6a342e162f9d50ff6f7d0 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sat, 25 Mar 2023 12:29:58 +0900 Subject: [PATCH 12/14] Update numerical_methods/bisection_method.c Co-authored-by: David Leal --- numerical_methods/bisection_method.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index 78a349b2ff..b60e782822 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -93,6 +93,8 @@ static void test() EPSILON); // the algorithm works as expected assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) < EPSILON); // the algorithm works as expected + + printf("All tests have successfully passed!\n"); } /** From f9b6a48f514d6bbbd9d1e4f63a6b8efefd0b9865 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sat, 25 Mar 2023 12:30:06 +0900 Subject: [PATCH 13/14] Update numerical_methods/bisection_method.c Co-authored-by: David Leal --- numerical_methods/bisection_method.c | 1 + 1 file changed, 1 insertion(+) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index b60e782822..a35c6ecc9d 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -16,6 +16,7 @@ #include /// for assert #include /// for fabs +#include /// for IO operations #define EPSILON 0.0001 // a small positive infinitesimal quantity #define NMAX 50 // maximum number of iterations From 0477a46656b24d6feee2d99471114ebeb467c298 Mon Sep 17 00:00:00 2001 From: Aybars Nazlica Date: Sat, 25 Mar 2023 13:32:46 +0900 Subject: [PATCH 14/14] update docs --- numerical_methods/bisection_method.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c index a35c6ecc9d..ce790f441f 100644 --- a/numerical_methods/bisection_method.c +++ b/numerical_methods/bisection_method.c @@ -22,10 +22,12 @@ #define NMAX 50 // maximum number of iterations /** - * @brief Function to check if two values have the same sign - * @param a First value - * @param b Second value - * @returns `sign` + * @brief Function to check if two input values have the same sign (the property + * of being positive or negative) + * @param a Input value + * @param b Input value + * @returns 1.0 if the input values have the same sign, + * @returns -1.0 if the input values have different signs */ double sign(double a, double b) { @@ -34,9 +36,9 @@ double sign(double a, double b) } /** - * @brief Continuous function for root-finding + * @brief Continuous function for which we want to find the root * @param x Real input variable - * @returns `function evaluation result` + * @returns The evaluation result of the function using the input value */ double func(double x) { @@ -95,7 +97,7 @@ static void test() assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) < EPSILON); // the algorithm works as expected - printf("All tests have successfully passed!\n"); + printf("All tests have successfully passed!\n"); } /**