2020-05-26 01:26:18 +03:00
|
|
|
/**
|
|
|
|
* @file
|
2020-05-29 19:34:58 +03:00
|
|
|
* \brief Find approximate solution for \f$f(x) = 0\f$ using
|
2020-05-26 01:26:18 +03:00
|
|
|
* Newton-Raphson interpolation algorithm.
|
2020-06-06 21:51:49 +03:00
|
|
|
*
|
|
|
|
* \author [Krishna Vedala](https://github.com/kvedala)
|
2020-06-28 22:18:52 +03:00
|
|
|
*/
|
2020-04-08 22:31:00 +03:00
|
|
|
|
2020-05-29 19:34:58 +03:00
|
|
|
#include <complex.h> /* requires minimum of C99 */
|
|
|
|
#include <limits.h>
|
2020-04-08 22:31:00 +03:00
|
|
|
#include <math.h>
|
2020-05-29 19:34:58 +03:00
|
|
|
#include <stdio.h>
|
2020-04-08 22:31:00 +03:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2020-05-26 01:26:18 +03:00
|
|
|
#define ACCURACY 1e-10 /**< solution accuracy */
|
|
|
|
|
2020-04-08 22:31:00 +03:00
|
|
|
/**
|
2020-05-26 01:26:18 +03:00
|
|
|
* Return value of the function to find the root for.
|
|
|
|
* \f$f(x)\f$
|
2020-04-08 22:31:00 +03:00
|
|
|
*/
|
2020-05-26 01:26:18 +03:00
|
|
|
double complex func(double complex x)
|
2020-04-08 22:31:00 +03:00
|
|
|
{
|
|
|
|
return x * x - 3.; /* x^2 = 3 - solution is sqrt(3) */
|
|
|
|
// return x * x - 2.; /* x^2 = 2 - solution is sqrt(2) */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-05-26 01:26:18 +03:00
|
|
|
* Return first order derivative of the function.
|
|
|
|
* \f$f'(x)\f$
|
2020-04-08 22:31:00 +03:00
|
|
|
*/
|
2020-05-29 19:34:58 +03:00
|
|
|
double complex d_func(double complex x) { return 2. * x; }
|
2020-04-08 22:31:00 +03:00
|
|
|
|
2020-05-26 01:26:18 +03:00
|
|
|
/**
|
|
|
|
* main function
|
|
|
|
*/
|
2020-04-08 22:31:00 +03:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
double delta = 1;
|
|
|
|
double complex cdelta = 1;
|
|
|
|
|
|
|
|
/* initialize random seed: */
|
|
|
|
srand(time(NULL));
|
|
|
|
|
2020-05-26 01:26:18 +03:00
|
|
|
/* random initial approximation */
|
2020-04-09 15:56:41 +03:00
|
|
|
double complex root = (rand() % 100 - 50) + (rand() % 100 - 50) * I;
|
2020-04-08 22:31:00 +03:00
|
|
|
|
|
|
|
unsigned long counter = 0;
|
2020-05-26 01:26:18 +03:00
|
|
|
/* iterate till a convergence is reached */
|
|
|
|
while (delta > ACCURACY && counter < ULONG_MAX)
|
2020-04-08 22:31:00 +03:00
|
|
|
{
|
2020-05-26 01:26:18 +03:00
|
|
|
cdelta = func(root) / d_func(root);
|
2020-04-08 22:31:00 +03:00
|
|
|
root += -cdelta;
|
|
|
|
counter++;
|
|
|
|
delta = fabs(cabs(cdelta));
|
|
|
|
|
|
|
|
#if defined(DEBUG) || !defined(NDEBUG)
|
|
|
|
if (counter % 50 == 0)
|
|
|
|
{
|
|
|
|
double r = creal(root);
|
|
|
|
double c = cimag(root);
|
|
|
|
|
2020-05-29 19:34:58 +03:00
|
|
|
printf("Iter %5lu: Root: %4.4g%c%4.4gi\t\tdelta: %.4g\n", counter,
|
|
|
|
r, c >= 0 ? '+' : '-', c >= 0 ? c : -c, delta);
|
2020-04-08 22:31:00 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
double r = creal(root);
|
2020-05-26 01:26:18 +03:00
|
|
|
double c = fabs(cimag(root)) < ACCURACY ? 0 : cimag(root);
|
2020-04-08 22:31:00 +03:00
|
|
|
|
|
|
|
printf("Iter %5lu: Root: %4.4g%c%4.4gi\t\tdelta: %.4g\n", counter, r,
|
|
|
|
c >= 0 ? '+' : '-', c >= 0 ? c : -c, delta);
|
|
|
|
|
|
|
|
return 0;
|
2020-06-06 21:51:49 +03:00
|
|
|
}
|