/**
 * An illustration of different mechanisms for computing x^n.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of October 1999
 */
public class Exponentiation {

  // +---------+-------------------------------------------------
  // | Methods |
  // +---------+

  /**
   * Compute x^n by multiplying x*x*...*x n times.  Uses
   * iteration as the mechanism for repetition.
   */
  public static double expA(double x, int n) {
    // Handle negative exponents.  x^(-n) = 1/(x^n)
    if (n < 0) {
      return 1/expA(x,-n);
    }
    // Prepare to compute the product.
    double product = 1;
    // Multiply by each x.  (Note that 1*x*x*...*x = x*x*...*x.)
    for (int i = 0; i < n; ++i) {
      product = product * x;
    } // for
    // That's it, we're done.
    return product;
  } // expA(double,int)  

  /**
   * Compute x^n by multiplying x*x*...*x n times.  Uses
   * recursion as the mechanism for repetition.
   */
  public static double expB(double x, int n) {
    // Handle negative exponents.  x^(-n) = 1/(x^n)
    if (n < 0) {
      return 1/expB(x,-n);
    } // if (n < 0)
    // Base case: x^0 is 1.
    if (n == 0) {
      return 1;
    } // if (n == 0)
    // Recursive case: x*x*...*x = x*(x*...*x)
    // That is: x^n = x*(x^(n-1))
    else {
      return x * expB(x, n-1);
    } // Recursive case, if (n > 0)
  } // expB(double,int)  

  /**
   * Compute x^n by a recursive divide-and-conquer algorithm.
   */
  public static double expC(double x, int n) {
    // Handle negative exponents.  x^(-n) = 1/(x^n)
    if (n < 0) {
      return 1/expB(x,-n);
    } // if (n < 0)

    // Base case: x^0 is 1.
    if (n == 0) {
      return 1;
    } // Base case: n == 0

    // Recursive case (when n is odd)
    //   x*x*...*x = x*(x*...*x)
    //   That is: x^n = x*(x^(n-1))
    else if (n % 2 == 1) {
     return x * expC(x,n-1);
    } // Recursive case (when n is odd)

    // Recursive case (when n is even)
    //   Let n be 2k
    //   x^n = x^(2k) = x^k * x^k
    else {
      int k = n/2;
      double tmp = expC(x,k);
      return tmp*tmp;
    } // Recursive case (when n is even)
  } // expC
} // class Exponentiation

