-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
/
Copy pathsecant_method.c
80 lines (69 loc) · 2.32 KB
/
secant_method.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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;
}