public class NumerikImplementations{
    
    public static Vektor newtonRnRn(FunctionRnRn f,Vektor x, int k, double tol){
	Vektor res = x;//f.f(x);
	while(Vektor.euklNorm(f.f(res))>tol&&k>0){
	    QuadMatrix fp = f.fp(res);
	    //Vektor tmp = ((f.f(res)).mult(-1)).plus((fp.Ax(res.mult(-1))));
	    /*Vektor tmp = f.f(res);
	    tmp.mult(-1.0);
	    //res.mult(-1.0);
	    Vektor tmp2 = fp.Ax(res);
	    Vektor tmp1 = tmp.plus(tmp2);
	    res = fp.Ax_b(tmp1);
	    /
	    Vektor a = f.f(res);
	    a.mult(-1.0);
	    Vektor tmp = fp.Ax_b(a);
	    res = tmp.plus(res);*/			

	    Vektor minusf = f.f(res);
	    minusf.mult(-1);
	    Vektor deltaX = fp.Ax_b(minusf);
	    res = res.plus(deltaX);

	    k--;
	}//if(Vektor.euklNorm(f.f(res))>tol)
	// System.out.print(Vektor.euklNorm(f.f(res))+"  ");
	
	return res;
	
    }


 
     /*hier wird die Nullstelle dieser Funktion, die diese Klasse
     *repräsentiert mittels Newton-Verfahren berechnet.
     *als Startwert muss ein Vektor mit Startwerten übergeben werden
     *als weitere Parameter muessen die Höchstschrittmenge k und
     *die Fehlertoleranz tol angegeben werden.
     *
    public static Vektor newtonRnRn(FunctionRnRn f,Vektor x, int k, double tol){
		//die Iteration:
		for(int i=0; i<k; i++){
	    	Matrix Z = f.fp(x);
			Vektor fx=f.f(x);
			for(int j=0; j<x.getLength(); j++)
			    fx.setElement((-1.0)*fx.getElement(j),j);
			Vektor tmp = Z.Ax(fx);
			if(Vektor.euklNorm(tmp)<=(tol)){
				System.out.println("\tDie Genauigkeit "+tol+" wurde nach "+i+" Iterationen erreicht.");	
				i=k;
				return x;
			}
			else{
				for(int j=0; j<x.getLength(); j++)
		    	x.setElement(x.getElement(j)+tmp.getElement(j),j);
	   		}
		}
		return x;
    }
    */
   public static double newton(double start, Function f, double xacc, double facc, int maxit){
        double xalt = start;//f.f(start);
        double xneu;
        int i=0;
        while(true){
            i++;

            //Newton Verfahren
            xneu=xalt-(f.f(xalt)/f.fp(xalt));

            double fehler1 = Math.abs(xalt-xneu);
            double fehler2 =Math.abs(f.f(xneu));
            //Protokollausgabe
            System.out.println("X"+i+" = "+xneu+"\n\t\tAbschätzung |X"+i+"-X"+(i-1)+"|= "+fehler1+"\n\t\tAbschätzung |f(X"+i+")|="+fehler2+"\n");
            //Abbruchbedingung
            if(fehler1<=xacc){
                System.out.println("Abbruch auf Grund |X"+i+"-X"+(i-1)+"|= "+fehler1+"<"+xacc);
                break;
            }
            if(i>maxit){
                System.out.println("Abbruch auf Grund zu vieler Versuche. \n\t\tERGEBNIS UNBRAUCHBAR return INFINITY");
                return Double.POSITIVE_INFINITY;

            }
            if(fehler2<facc){
                System.out.println("\n\n\tAbbruch auf Grund |f(X"+i+")|< "+facc+"\n\n");    
                break;
        }
            xalt=xneu;

        }
        return xneu;
    } 


   
}
