package hw04;

public class SquareRoot {
	
	public static double epsilon = 1E-6;
	
	public static void setEpsilon(double newEpsilon) { epsilon=newEpsilon; }
	
	private double n;
	private int depth;
	private Tree guesses;
	
	public SquareRoot(double n) { this.n=n; }
	public int getDepth() { return depth; }
	public Tree getGuesses() { return guesses; }
	
	public double sqrt() {
		depth=0;
		if (n<0) return Double.NaN;
		return sqrt(n/2);
	}
	
	public double sqrt(double g) {
		if (guesses==null) guesses=new Tree(g);
		else guesses.insert(g);
		double error = n-(g*g);
		if (Math.abs(error) < epsilon) return g;
		// if (Math.abs(error)== Double.POSITIVE_INFINITY) return g;
		depth++;
		if (depth>300) {
			System.out.println(" ===> Maximum depth exceeded!");
			return g;
		}
		// System.out.println("DEBUG: n=" + n + " g=" + g + " error=" + error + " depth=" + depth);
		return sqrt(0.5*(g+n/g));		
	}
	
	
	
	static public void main(String[] args) {
		System.out.println("Calculating square root of command line arguments");
		for(String arg : args) {
			double n = Double.parseDouble(arg);
			SquareRoot sr = new SquareRoot(n);
			double g = sr.sqrt();
			double mg = Math.sqrt(n);
			System.out.println("sqrt(" + n + ")=" + g + " Math.sqrt(" + n + ")=" + mg +
					" Difference=" + (Math.abs(g-mg))+ " depth=" + sr.getDepth());
			System.out.println("  Guesses: " + sr.getGuesses());
		}
		System.out.println("\nTry again with a smaller epsilon.");
		setEpsilon(1E-14);
		for(String arg : args) {
			double n = Double.parseDouble(arg);
			SquareRoot sr = new SquareRoot(n);
			double g = sr.sqrt();
			double mg = Math.sqrt(n);
			System.out.println("sqrt(" + n + ")=" + g + " Math.sqrt(" + n + ")=" + mg +
					" Difference=" + (Math.abs(g-mg))+ " depth=" + sr.getDepth());
			System.out.println("  Guesses: " + sr.getGuesses());
		}
	}

}
