import SimpleOutput;
import Fibonacci;

/**
 * An attempt to compare the more efficient techniques for
 * computing Fibonacci numbers.  Intended as part of an answer 
 * key for HW6 of CS152 99S.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of March 1999
 */
public class FibTimer {
  // +------+----------------------------------------------------
  // | Main |
  // +------+

  /**
   * Get some values of N and compute.
   */
  public static void main(String[] args) {
    // Create an array of inputs.
    long[] vals = new long[args.length];
    // Create an array of results.
    long[] results = new long[args.length];
    // Two time values, used to determine how long the various
    // computations take.
    long start;
    long stop;
    // The wonderful thing that does all the computation.
    Fibonacci computer = new Fibonacci();
    // And something for output.
    SimpleOutput out = new SimpleOutput();
    // It turns out to be best to repeat computation if we're
    // going to get any useful results (since Fibonacci numbers
    // get too large too fast, there's not a clear way to
    // distinguish them by large inputs).  Of course, this may
    // give an unfair bias to the dynamic programming method.
    int REPETITIONS = 1000;

    // Fill in the values.  Use 0 if the user gives a bad
    // value.  This is intended for testing only, so the
    // user interface is primitive at best.
    for (int i = 0; i < args.length; ++i) {
      try { vals[i] = Long.parseLong(args[i]); }
      catch (Exception e) { }
    } // for

    // Determine how long the dynamic processing technique takes
    start = System.currentTimeMillis();
    for (int j = 0; j < REPETITIONS; ++j) {
      for (int i = 0; i < vals.length; ++i) {
        results[i] = computer.fibdp(vals[i]);
      } // for
    } 
    stop = System.currentTimeMillis();
    // Report
    out.println("Dynamic programming method: ");
    for (int i = 0; i < vals.length; ++i) {
      out.println("  fibdp(" + vals[i] + ") = " + results[i]);
    } // for
    out.println("  COMPUTATION TOOK " + (stop-start) + " MILLISECONDS");

    // Determine how long the iterative technique takes
    start = System.currentTimeMillis();
    for (int j = 0; j < REPETITIONS; ++j) {
      for (int i = 0; i < vals.length; ++i) {
        results[i] = computer.fibit(vals[i]);
      } // for
    } // for
    stop = System.currentTimeMillis();
    // Report
    out.println("Iterative method: ");
    for (int i = 0; i < vals.length; ++i) {
      out.println("  fibit(" + vals[i] + ") = " + results[i]);
    } // for
    out.println("  COMPUTATION TOOK " + (stop-start) + " MILLISECONDS");

    // Determine how long the other recursive technique takes
    start = System.currentTimeMillis();
    for (int j = 0; j < REPETITIONS; ++j) {
      for (int i = 0; i < vals.length; ++i) {
        results[i] = computer.fibrec(vals[i]);
      } // for
    }
    stop = System.currentTimeMillis();
    // Report
    out.println("Other recursive method: ");
    for (int i = 0; i < vals.length; ++i) {
      out.println("  fibrec(" + vals[i] + ") = " + results[i]);
    } // for
    out.println("  COMPUTATION TOOK " + (stop-start) + " MILLISECONDS");
  }
    
} // class FibTimer

