#include <stdio.h>
#include <math.h>

#include "bisection.c"
#include "newton_raphson.c"

static double regula_falsi(double (*f)(double), double a, double b,
        double tolerance, unsigned int *steps, unsigned int max_steps,
        double approximation, int error_per_step)
{
    int side = 0;
    double c, fc, fa = f(a), fb = f(b);

    for( *steps = 1; *steps < max_steps; (*steps)++ ) {
        c = (fa * b - fb * a) / (fa - fb);

        if ( error_per_step )
            printf("step %2d error: %.3E (%3f%%)\n", *steps,
                fabs(approximation - c),
                100 * fabs(c - approximation) / approximation);

        if ( fabs(b - a) < tolerance * fabs(b + a) )
            break;

        fc = f(c);

        if ( fc * fb > 0 ) {
            b = c;
            fb = fc;

            if( side == -1 )
                fa /= 2;

            side = -1;
        } else if (fa * fc > 0) {
            a = c;
            fa = fc;

            if( side == 1 )
                fb /= 2;

            side = 1;
        } else
            break;
    }

    return c;
}

#ifdef MAIN_sqrt

static inline double f(double x) { return x * x - 2; }

static inline double df(double x) { return 2 * x; }

int main(void)
{
    unsigned int steps;

    double approx = 1.41421356237309504880168872420, result;
    printf("√2 is approximate       = %.20f\n", approx);

    result = bisect(&f, 1, 2, 10e-12, &steps, 100, approx, 0);
    printf("√2 using bisection      = %.20f (%d steps)\n", result, steps);

    result = regula_falsi(&f, 1, 2, 10e-12, &steps, 100, approx, 0);
    printf("√2 using regula falsi   = %.20f (%d steps)\n", result, steps);

    result = newton_raphson(&f, &df, 1.4, 10e-12, &steps, 100, approx, 0);
    printf("√2 using newton-raphson = %.20f (%d steps)\n", result, steps);

    return 0;
}

#endif
