package utils;

interface Function {
  public double f(double x);
}

class AnnuityFunction implements Function {
  public double f(double r) {
    return (12 * 250 / r) * Math.pow((1 + r / 12), 240) - 1 - 250000;
  }
}

public class RootFinder {

  public static void main(String args[]) {
    double i = bisection(0.1, 0.2, new AnnuityFunction());
    System.out.println("i=" + i);
  }

  public static double bisection(double a, double b, Function fi) {
    double m = 0.0;
    int trys = 0;
    while (isNotCloseEnough(a, b)) {
      m = (a + b) / 2;

      // Check to see if root was hit at midpoint
      if (fi.f(m) == 0) break;
      if (fi.f(a) * fi.f(m) < 0)
        b = m;
      else
        a = m;
      trys++;
    } // End while
    System.out.println("done in:" + trys + " trys");
    return m;
  }

  public static final double falsePosition(double a, double b, Function fi) {
    double xold = a,
        xn = b,
        m = 0.0;

    while (isNotCloseEnough(a, b)) {
      xold = xn;
      m = (a * fi.f(b) - b * fi.f(a)) / (deltaF(b, a, fi));

      // Check to see if root was hit
      if (fi.f(m) == 0) break;
      if (fi.f(a) * fi.f(m) < 0)
        b = m;
      else
        a = m;

      xn = m;
    }
    return m;
  } // End False Position

  private static final double deltaF(double b, double a, Function fi) {
    return fi.f(b) - fi.f(a);
  }


  public static final double secant(double a, double b, Function fi) {
    double m = 0.0;

    while (isNotCloseEnough(a, b)) {
      m = (a * fi.f(b) - b * fi.f(a)) / (deltaF(b, a, fi));
      a = b;
      b = m;
    }
    return m;
  } // End Secant

  private static final boolean isNotCloseEnough(double a, double b) {
    double stopCriterion = 0.0000001;
    return Math.abs(a - b) > stopCriterion;
  }


}