/**
 * Distance Computation
 * This program computes Euclidean distance between two points in n-space.
 *
 * @author Chris Clifton
 *
 * @recitation w4 (Chris Clifton)
 *
 * @date January 26, 2011
 *
 */
import java.lang.Math;
import java.util.Date;
import java.util.Scanner;

public class Lec5Distc extends Thread
{
  public double distance = 0;
  private double x[], y[]; // Arrays to compute distance on
  private int begin,end; // Dimensions to compute on

  public Lec5Distc(double a[], double b[],int bg, int en)
      // Set up what this instance is supposed to do when it runs.
  {
    x = a;
    y = b;
    begin = bg;
    end = en;
  }
  
  public void run()
      // What to do when "start" is called (from Thread class)
  {
    distance = SumSquareDiff(x,y,begin,end);
  }
  
  public static double SumSquareDiff(double[] a, double[] b, int begin, int end)
    // Requires:  a.length = b.length; no null values in a or b
    // Produces:  Euclidean distance between a and b (>0)
  {
    double sum = 0;
    for (int i=begin; i<end; i++) {
      sum = sum + (a[i]-b[i])*(a[i]-b[i]);
    }
    return sum;
  }
  
  public static double EuclideanDistance(double[] a, double[] b)
    // Requires:  a.length = b.length; no null values in a or b
    // Produces:  Euclidean distance between a and b (>=0)
  {
    Lec5Distc first = new Lec5Distc(a,b,0,(int)Math.floor(a.length/3));
    Lec5Distc second = new Lec5Distc(a,b,(int)Math.floor(a.length/3)+1,(int)Math.floor(2*a.length/3));
    Lec5Distc third = new Lec5Distc(a,b,(int)Math.floor(2*a.length/3)+1,a.length);
    first.start(); // Start computation on the first third, but don't wait
    second.start(); // Start computation on the second third, don't wait
    third.start(); // Start computation on the last third, don't wait
    try {
      first.join(); // Wait for the first third to finish.
      second.join(); // Wait for the second third to finish.
      third.join(); // Wait for the second third to finish.
    } catch(InterruptedException e) { /* Ignore */ }
    return Math.sqrt(first.distance+second.distance+third.distance);
  }

  public static final int DIMENSIONS = 10000000;
  public static void main(String args[])
  {
    double[] a = new double[DIMENSIONS];
    double[] b = new double[DIMENSIONS];
    
    for (int i=0; i < DIMENSIONS; i++) {
      a[i] = Math.random();
      b[i] = Math.random();
    }

    long time = new Date().getTime();
    double dist = EuclideanDistance(a,b);
    time = new Date().getTime() - time;
    System.out.println("Distance computed is " + dist);
    System.out.println("Distance computation took " + time + " milliseconds"); 
  }
}
