// 
//  
// Newton-Raphson (Secant)-Bisection combined root finding method 
//  
//  

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

//============= Function definition ================

class fb extends f_x
{
   public double func (double x)
   { return Math.log(x*x)-0.7;}
}
//===========================================================

public class NA11
{

public static double dfx(f_x f,double x,double h)
{ //Derivative formula
  double hh=1.0/h; 
  return (-f.func(x+2.0*h)+8.0*f.func(x+h)-8.0*f.func(x-h)+f.func(x-2.0*h))/12.0*hh;
}

public static double newton_bisection(f_x fx, double x1, double x2)
{
double xacc=1.0e-10; //accuracy
double h=0.0001; //derivative function step
int MAXIT=100;  //Maximumnumber of iterations
int j;
double dfr,dx,dxold,fr,fh,fl;
double temp,b,a,r;
fl=fx.func(x1);
fh=fx.func(x2);
//Check if a root is existed in the given region
if ((fl > 0.0 && fh > 0.0) || (fl < 0.0 && fh < 0.0))
System.out.println("There are no root in the given region or double root?");
if (fl == 0.0) return x1;
if (fh == 0.0) return x2;
if (fl < 0.0)   { a=x1;b=x2;} 
else            { b=x1;a=x2;}
r=0.5*(x1+x2); //midpoint value
dxold=Math.abs(x2-x1); 
dx=dxold; 
fr=fx.func(r);   //function value at midpoint
dfr=dfx(fx,r,h); //derivative of function value at midpoint 
for (j=1;j<=MAXIT;j++) 
{ 
if ((((r-b)*dfr-fr)*((r-a)*dfr-fr) > 0.0) || (Math.abs(2.0*fr) > Math.abs(dxold*dfr))) 
    { //bisection step
	  dxold=dx;
      dx=0.5*(b-a);
      r=a+dx;
      if (a == r) return r; //çözüm!!!!
    } 
else{ //Newton-Raphson (Secant) step
	  dxold=dx;
      dx=fr/dfr;
      temp=r;
      r -= dx;
      if (temp == r) return r;  //solution!!!!!
    }
if (Math.abs(dx) < xacc) return r; //solution!!!!!
fr=fx.func(r);
dfr=dfx(fx,r,h);
if (fr < 0.0) 
a=r;
else
b=r;
}
System.out.println("Maximum number of iterations are exceeded");
return 0.0; //program should never reach here
            //dummy return
}

     public static void main (String args[])  
     {  
	 fb f=new fb(); 
     double x0,x1;
     x0=Double.parseDouble(JOptionPane.showInputDialog(" lower root limit : "));
     x1=Double.parseDouble(JOptionPane.showInputDialog(" higher root limit : "));
     double r= newton_bisection(f,x0,x1);
     JOptionPane.showMessageDialog(null," root value  : "+r+"\nFunction value : "+f.func(r),
     "Newton-Raphson (Secant) - Bisection combined root finding method : ",JOptionPane.PLAIN_MESSAGE);
     System.exit(0); 
     } 
}