-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add secant method * Apply suggestions from code review Co-authored-by: Sharon "Cass" Cassidy <[email protected]> * fixed indentation * added more tests * better clarification for the tolerance parameter * removed redundant comments * chore: apply suggestions from code review --------- Co-authored-by: Sharon "Cass" Cassidy <[email protected]> Co-authored-by: scpires <[email protected]> Co-authored-by: David Leal <[email protected]>
- Loading branch information
1 parent
d222df7
commit 05ff277
Showing
1 changed file
with
80 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* @file | ||
* @brief [Secant Method](https://en.wikipedia.org/wiki/Secant_method) implementation. Find a | ||
* continuous function's root by using a succession of roots of secant lines to | ||
* approximate it, starting from the given points' secant line. | ||
* @author [Samuel Pires](https://github.com/disnoca) | ||
*/ | ||
|
||
#include <assert.h> /// for assert | ||
#include <math.h> /// for fabs | ||
#include <stdio.h> /// for io operations | ||
|
||
#define TOLERANCE 0.0001 // root approximation result tolerance | ||
#define NMAX 100 // maximum number of iterations | ||
|
||
/** | ||
* @brief Continuous function for which we want to find the root | ||
* @param x Real input variable | ||
* @returns The evaluation result of the function using the input value | ||
*/ | ||
double func(double x) | ||
{ | ||
return x * x - 3.; // x^2 = 3 - solution is sqrt(3) | ||
} | ||
|
||
/** | ||
* @brief Root-finding method for a continuous function given two points | ||
* @param x0 One of the starting secant points | ||
* @param x1 One of the starting secant points | ||
* @param tolerance Determines how accurate the returned value is. The returned | ||
* value will be within `tolerance` of the actual root | ||
* @returns `root of the function` if secant method succeed within the | ||
* maximum number of iterations | ||
* @returns `-1` if secant method fails | ||
*/ | ||
double secant_method(double x0, double x1, double tolerance) | ||
{ | ||
int n = 1; // step counter | ||
|
||
while (n++ < NMAX) | ||
{ | ||
// calculate secant line root | ||
double x2 = x1 - func(x1) * (x1 - x0) / (func(x1) - func(x0)); | ||
|
||
// update values | ||
x0 = x1; | ||
x1 = x2; | ||
|
||
// return value if it meets tolerance | ||
if (fabs(x1 - x0) < tolerance) | ||
return x2; | ||
} | ||
|
||
return -1; // method failed (maximum number of steps exceeded) | ||
} | ||
|
||
/** | ||
* @brief Self-test implementations | ||
* @returns void | ||
*/ | ||
static void test() | ||
{ | ||
// compares root values found by the secant method within the tolerance | ||
assert(secant_method(0.2, 0.5, TOLERANCE) - sqrt(3) < TOLERANCE); | ||
assert(fabs(secant_method(-2, -5, TOLERANCE)) - sqrt(3) < TOLERANCE); | ||
assert(secant_method(-3, 2, TOLERANCE) - sqrt(3) < TOLERANCE); | ||
assert(fabs(secant_method(1, -1.5, TOLERANCE)) - sqrt(3) < TOLERANCE); | ||
|
||
printf("All tests have successfully passed!\n"); | ||
} | ||
|
||
/** | ||
* @brief Main function | ||
* @returns 0 on exit | ||
*/ | ||
int main() | ||
{ | ||
test(); // run self-test implementations | ||
return 0; | ||
} |