
/* PHYS 307:  Solution to Homework #1. */

#include <stdio.h>
#include <math.h>

typedef double real;		/* convenient alias */

/* Global variables i and n_iter are used to bypass the argument list
   in passing data to and returning it from the functions g and solve.

   *** Bad programming practice, but very convenient! ***
*/

int i, n_iter;

real g(real z)
{
    /* Use global i to choose between homework options. */

    if (i == 1)
	return pow(z,3) - 3;
    else if (i == 2)
	return cos(z) - z;
    else
	return z*tan(z) - 1;
}

real solve(real z1, real z2, real epsilon)
{
    /* Use bisection until the range is less than the specified tolerance.
       Global n_iter is used to count iterations in the bisection loop. */

    real zm;
    while (z2 - z1 > epsilon) {
	zm = (z1 + z2)/2;
	if (g(zm)*g(z1) > 0)
	    z1 = zm;
	else			/* note no check for equality */
	    z2 = zm;
	n_iter++;
    }

    /* Perform one final false-position iteration. */

    return z1 + (z2 - z1) * (-g(z1)) / (g(z2) - g(z1));
}

main()
{
    real z1, z2, dz = 0.1, epsilon = 1.e-4, z;

    for (i = 1; i <= 3; i++) {

	/* Find an acceptable range [0, z2]. */

	z1 = 0;
	z2 = dz;
	while (g(z2)*g(z1) > 0) {
	    z1 = z2;
	    z2 += dz;
	}

	/* The range (z1, z2) brackets a root.  Solve for the root. */

	n_iter = 0;
	z = solve(z1, z2, epsilon);

	printf("i = %d, z1 = %f, z2 = %f, z = %f, g = %e, n = %d\n",
	       i, z1, z2, z, g(z), n_iter);
    }
}










//
