// 
//  
// Complex Newton-Raphson (Secant) method
//  
//  

import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import javax.swing.*;

abstract class cf_cx
{
  // The function
  abstract complex func(complex x);
  complex dfunc(complex x)
  { // complex numerical derivative of the function
   double hh=0.001;
   complex h=new complex(hh,hh);
   complex he=new complex(-hh,-hh);
   complex h2=new complex(2.0*hh,2.0*hh);
   complex he2=new complex(-2.0*hh,-2.0*hh);
   complex xah=complex.add(x,h);
   complex xa2h=complex.add(x,h2);
   complex xeh=complex.add(x,he);
   complex xe2h=complex.add(x,he2);
   complex fe2h=complex.multiply(func(xe2h),(1.0/12.0));
   complex feh=complex.multiply(func(xeh),(-8.0/12.0));
   complex fah=complex.multiply(func(xah),(8.0/12.0));
   complex fa2h=complex.multiply(func(xa2h),(-1.0/12.0));
   complex df=complex.add(fe2h,complex.add(feh,complex.add(fah,fa2h)));
   df=complex.divide(df,h);
   return df;
  }
}

class fa extends cf_cx
{  //complex function
  // example  f=x*x+1
complex func(complex x)
{ complex f=complex.add(complex.multiply(x,x),1.0);
  return f;
}
}

public class NA6
{	
public static complex newton(cf_cx f,complex x)
{
int nmax=50;
double tolerance=1.0e-8;
complex fx,dfx;
for(int i=0;i<nmax;i++)
{
  fx=f.func(x);
  dfx=f.dfunc(x);
  //x=complex.add(x,complex.multiply(complex.divide(fx,dfx),-1.0));
  x=complex.substract(x,complex.divide(fx,dfx));
  if(complex.abs(fx)<tolerance) { return x;}
}
JOptionPane.showMessageDialog(null,"Warning : MAximum number of iteration is exceeded \n"+
   " çözüm geçerli olmıyabilir","MAXİMUM ITERATION NUMBER WARNING",JOptionPane.WARNING_MESSAGE);
return x;
}
     public static double[] verigir(String s)
     {
     String s1=JOptionPane.showInputDialog(s);        
     StringTokenizer token=new StringTokenizer(s1);
     int n=token.countTokens()-1;
     int m=n+1;
     double a[]=new double[m];
     int j=0;           
     while(token.hasMoreTokens())
     {
     Double ax=new Double(token.nextToken());
     a[j++]=ax.doubleValue();
     }
     return a; 
     }

     public static void main (String args[])  
     {
	 fa f=new fa();     
     double x0[]=verigir("First complex root estimation (two number with a space in between) z=(a+bi) : ");
     complex x=new complex(x0[0],x0[1]);
     complex r= newton(f,x);
     complex ff=f.func(r);
     JOptionPane.showMessageDialog(null," root of the complex function  : "+r.toString()+"\nFunction value : "+ff.toString(),
     "Newton-Raphson (Secant) complex root finding : ",JOptionPane.PLAIN_MESSAGE);
     } 
}
