import java.lang.Math;

/**
 * Resuelve una ecuacion cuadratica.
 *
 * Encuentra las dos raices que resuelven la ecuacion cuadratica:
 * 	ax^2 + bx + c = 0.
 *
 * Utiliza la formula general (tambien conocida
 * coloquialmente como el "chicharronera 1 y 2")
 * y el metodo de Newton-Rapson.
 *
 * Parametros:
 *	a -- coeficiente cuadratico (debe ser distinto de 0)
 * 	b -- coeficiente lineal
 * 	c -- termino independiente
 *
 * Error:
 * 	Si (a == 0)
 *
*/
public class CuadraticaCodConFunciones {


   /**
    * Evalua la funcion cuadratica
    * @param x Valor en que se evaluara la funcion
    *
    * @return Evaluacion de la funcion cuadratica en x
    */
   public static double f(double x, double a, double b, double c) {
      return (x * x * a + x * b + c);
   }

   /**
    * Evalua la derivada de la funcion cuadratica
    * @param x Valor en que se evaluara la funcion
    *
    * @return Evaluacion de la funcion derivada en x
    */
   public static double df(double x, double a, double b) {
      return (2.0 * x * a + b);
   }

   /**
    * Evalua el valor X en la funcion cuadratica
    * @param x Valor en que se evaluara la funcion
    *
    * @return Evaluacion de la funcion cuadratica en x
    */
   public static void evalua(double x, double a, double b, double c) {
      System.out.println("  Evaluacion Raiz (" + x + "): " + f(x, a, b, c));
   }

   /**
    *  Metodo Newton-Raphson: x = x - f(x)/f'(x)
    * @param x Valor inicial para hacer la busqueda de la raiz
    * @param ni Numero de iteraciones
    *
    * @return La raiz buscada
    */
   public static double metodoNewtonRapson(double x, int ni, double a, double b, double c) {
      for (int i = 0; i < ni; i++) {
         x = x - (f(x, a, b, c) / df(x, a, b));
      }
      return x;
   }


   // Funcion Principal ....
   public static void main(String[] args) {

      // Coeficientes del polinomio
      double A = 1.0, B = 4.0, C = 1.0, d;
      // Raices del polinomio
      double X1, X2, x;


      // Calculo del discriminante
      d = B * B - 4.0 * A * C;
      // Raices reales
      if (d >= 0.0) {
         System.out.println("");
         System.out.println("Raices Reales (" + A + ")X^2 + (" + B + ")X + (" + C + ") = 0");
         System.out.println("Chicharronera 1");
         X1 = (-B + Math.sqrt(d)) / (2.0 * A);
         X2 = (-B - Math.sqrt(d)) / (2.0 * A);
         // Evalua el calculo de la raiz
         evalua(X1, A, B, C);
         // Evalua el calculo de la raiz
         evalua(X2, A, B, C);
         System.out.println("");


         System.out.println("Chicharronera 2");
         X1 = (-2.0 * C) / (B + Math.sqrt(d));
         X2 = (-2.0 * C) / (B - Math.sqrt(d));;

         // Evalua el calculo de la raiz
         evalua(X1, A, B, C);
         // Evalua el calculo de la raiz
         evalua(X2, A, B, C);
         System.out.println("");


         // Metodo Newton-Raphson
         // x = x - f(x)/f'(x)
         System.out.println("Metodo Newton-Raphson");
         x = X1 - 1.0;
         x = metodoNewtonRapson(x, 8, A, B, C);
         evalua(x, A, B, C);

         x = X2 - 1.0;
         x = metodoNewtonRapson(x, 8, A, B, C);
         evalua(x, A, B, C);

      } else {
         // Raices complejas
         System.out.println("Raices Complejas ...");
      }
   }
}