//  -----------------------------------------------------------------
//  -------  Numerische Mathematik                   ----------------
//  -------  Ib 03                                   ----------------
//  -------  Mueller-Verfahren                       ----------------
//  -------                                          ----------------
//  -------  2004 November 11     M.Vogel            ----------------
//  -----------------------------------------------------------------
import java.lang.*;

public class Mueller
{
   static public void main( String[] args )
   {
// ------------------------------------------------------------------
// ---------          Mueller Verfahren                --------------
// ------------------------------------------------------------------
      int j = 2                                        ;
      int M  = 500                                     ;
      double  err = 1.0E-8                             ;
      double  x                                        ;
      Complex a ,b ,c , z1 , z2 , nenn =new Complex()  ;

      InOut.println("")                                ;
      InOut.println("Start-Wert für Nullstelle eingeben ")  ;
      InOut.println("")                                ;
      x = InOut.getDouble()                            ;
      Complex p0 = new Complex(x , Math.random()*10.0-5.0 )               ;
      Complex p1 = new Complex(x-0.5 , Math.random()*10.0-5.0 )           ;
      Complex p2 = new Complex(x+0.5 , Math.random()*10.0-5.0 )           ;

      do
	  {  c = f( p2 )                                   ;

	     nenn = p0.mult(p0.sub(p0,p2) , p0.sub(p1,p2)) ;
	     nenn = p0.mult(nenn, nenn.sub(p0,p1))         ;
         z1 = p0.mult( c.sub(p0,p2) , c.sub(f(p1),f(p2)) ) ;
	     z2 = p1.mult( c.sub(p1,p2) , c.sub(f(p0),f(p2)) ) ;

	     b =  z1.sub(z1.mult(z1 , p0.sub(p0,p2)), z2.mult(z2 , p1.sub(p1,p2))  ) ;
	     b =  b.div(b , nenn)                          ;

	     a =  z2.div(z2.sub(z2 , z1) , nenn )          ;

         nenn = b.sqrt(b.sub(b.mult(b,b) , a.mult(a.mult(a,4.0) , c) ) ) ;
		 if (b.real(b) < 0 ) nenn = b.sub(b,nenn)      ;
		    else
				nenn = b.add(b,nenn)                   ;

         a  = p2.sub(p2,nenn.div(c.mult(c,2.0) , nenn));
         p0 = p1                                       ;
		 p1 = p2                                       ;
		 p2 = a                                        ;

		 j++                                           ;
	     InOut.print(" Nullstelle "+j+" : ")           ;
	     InOut.print(p2.real(p2), 4, 6)                ;
	     InOut.print(" +  i * ")                       ;
	     InOut.println(p2.imag(p2), 4, 6)              ;
	  }
	  while( (p2.betrag(p2.sub(p2,p1)) > err ) && (j<M) ) ;

    }



    static private Complex f(Complex x)
    {  Complex z = new Complex()                       ;

    // Aufgabe 3.7.1b):

       z = z.mult(x,1.0)                                 ;
       z = z.add(z, 1.0)                               ;
       z = z.mult(x,z)                                 ;
       z = z.add(z, 3.0)                               ;
       z = z.mult(x,z)                                 ;
       z = z.add(z, 2.0)                               ;
       z = z.mult(x,z)                                 ;
       z = z.add(z, 2.0)                               ;


//      z = z.add(x,1.0)                                ;
//       z = z.mult(x,z)                                 ;
//       z = z.add(z, 3.0)                               ;
//       z = z.mult(x,z)                                 ;
//       z = z.add(z, 2.0)                               ;
//       z = z.mult(x,z)                                 ;
//       z = z.add(z, 2.0)                               ;


//       Complex r1 = new Complex(-0.5 , 0.5*Math.sqrt(3.0) )  ;
//       Complex r2 = new Complex(-0.5 ,-0.5*Math.sqrt(3.0) )  ;
//       z = z.div(z , z.mult( x.sub(x,r1) , x.sub(x,r2) )  )  ;
       return(z)                                       ;
    }
}


//  -----------------------------------------------------------------
//  -------             class Complex                ----------------
//  -------                                          ----------------
//  -------  2001 November 22     M.Vogel            ----------------
//  -----------------------------------------------------------------


class Complex {

	double a,b;
	public Complex() {  a=0 ;  b=0;  }
	public Complex(Complex c) { this.a=c.a ; this.b=c.b ; 	}
	public Complex(double x, double y) { this.a=x ; this.b=y ; }

	public double real(Complex x) {
		double z = x.a ;
		return(z);
	}

	public double imag(Complex x) {
		double z = x.b ;
		return(z);
	}

	public Complex conj(Complex x) {

		Complex z=new Complex();
		z.a= x.a ;
		z.b=-x.b ;
		return(z);
	}

	public Complex mult(Complex x, Complex y) {

		Complex z=new Complex();
		z.a=x.a*y.a-x.b*y.b;
		z.b=x.a*y.b+x.b*y.a;
		return(z);
	}

	public Complex mult(Complex x, double y) {

		Complex z=new Complex();
		z.a=x.a*y ;
		z.b=x.b*y ;

		return(z);
	}

	public Complex div(Complex x, Complex y) {

		Complex z=new Complex()       ;
		double b = y.betrag(y)        ;
		b = 1.0 / (b*b)               ;
		z = x.mult(x, y.conj(y))      ;
		z = z.mult(z, b )             ;

		return(z)                     ;
	}

	public Complex add(Complex x, Complex y) {

		Complex z=new Complex();
		z.a=x.a+y.a;
		z.b=x.b+y.b;

		return(z);
	}

	public Complex add(Complex x, double y) {

		Complex z=new Complex();
		z.a=x.a+y ;
		z.b=x.b   ;

		return(z);
	}

	public Complex sub(Complex x, Complex y) {

		Complex z=new Complex();
		z.a=x.a-y.a;
		z.b=x.b-y.b;

		return(z);
	}

	public Complex sqrt(Complex x) {

		Complex z=new Complex()     ;
		double phi , r              ;
		r = x.betrag(x)             ;
		r = Math.sqrt(r)            ;
		phi = Math.atan2(x.b , x.a) ;
		phi = phi / 2.0             ;
		z.a = r * Math.cos(phi)     ;
		z.b = r * Math.sin(phi)     ;

		return(z);
	}

	public double betrag(Complex x) {

		return(Math.sqrt(x.a*x.a+x.b*x.b));

	}
}


