COSTA: COSt and Termination Analyzer for Java Bytecode
    
    package memory.jolden.bh;

/**
 * A class representing a three dimensional vector that implements
 * several math operations.  To improve speed we implement the
 * vector as an array of doubles rather than use the exising
 * code in the java.util.Vector class.
 **/
class MathVector implements Cloneable
{
  /**
   * The number of dimensions in the vector
   **/
  public final static int NDIM = 3;
  /**
   * An array containing the values in the vector.
   **/
  private double data[];

  /**
   * Construct an empty 3 dimensional vector for use in Barnes-Hut algorithm.
   **/
  MathVector()
  {
    data = new double[NDIM];
    for (int i=0; i < NDIM; i++) {
      data[i] = 0.0;
    }
  }

    MathVector(double[] d){
	data = d;
    }

  /**
   * Create a copy of the vector.
   * @return a clone of the math vector
   **/
    /*
  public Object clone() 
  {
    try {
      MathVector v = (MathVector)super.clone();
      v.data = new double[NDIM];
      
      for (int i = 0; i < NDIM; i++)
	v.data[i] = data[i];
	
      return v;
    } catch (CloneNotSupportedException e) {
      throw new Error();
    }
  }
    */

  /**
   * Create a copy of the vector.
   * @return a clone of the math vector
   **/
    public Object clone(){
	//MathVector v = new MathVector();
	double[] d = new double[NDIM]; 
	for (int i = 0; i < NDIM; i++)
	    d[i] = data[i];
	return new MathVector(d);	    
	//return v;
    }


  /**
   * Return the value at the i'th index of the vector.
   * @param i the vector index 
   * @return the value at the i'th index of the vector.
   **/
  final double value(int i)
  {
    return data[i];
  }

  /**
   * Set the value of the i'th index of the vector.
   * @param i the vector index
   * @param v the value to store
   **/
  final void value(int i, double v)
  {
    data[i] = v;
  }

  /**
   * Set one of the dimensions of the vector to 1.0
   * param j the dimension to set.
   **/
  final void unit(int j)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] = (i == j ? 1.0 : 0.0);
    }
  }

  /**
   * Add two vectors and the result is placed in this vector.
   * @param u the other operand of the addition
   **/
  final void addition(MathVector u)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] += u.data[i];
    }
  }

  /**
   * Subtract two vectors and the result is placed in this vector.
   * This vector contain the first operand.
   * @param u the other operand of the subtraction.
   **/
  final void subtraction(MathVector u)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] -= u.data[i];
    }
  }

  /**
   * Subtract two vectors and the result is placed in this vector.
   * @param u the first operand of the subtraction.
   * @param v the second opernd of the subtraction
   **/
  final void subtraction(MathVector u, MathVector v)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] = u.data[i] - v.data[i];
    }
  }

  /**
   * Multiply the vector times a scalar.
   * @param s the scalar value
   **/
  final void multScalar(double s)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] *= s;
    }
  }

  /**
   * Multiply the vector times a scalar and place the result in this vector.
   * @param u the vector
   * @param s the scalar value
   **/
  final void multScalar(MathVector u, double s)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] = u.data[i] * s;
    }
  }

  /**
   * Divide each element of the vector by a scalar value.
   * @param s the scalar value.
   **/
  final void divScalar(double s)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] /= s;
    }
  }

  /**
   * Return the dot product of a vector.
   * @return the dot product of a vector.
   **/
  final double dotProduct()
  {
    double s = 0.0;
    for (int i=0; i < NDIM; i++) {
      s += data[i] * data[i];
    }
    return s;
  }

  final double absolute()
  {
    double tmp = 0.0;
    for (int i = 0; i < NDIM; i++) {
      tmp += data[i] * data[i];
    }
    return Math.sqrt(tmp);
  }

  final double distance(MathVector v)
  {
    double tmp = 0.0;
    for (int i = 0; i < NDIM; i++) {
      tmp += ((data[i] - v.data[i]) * (data[i] - v.data[i]));
    }
    return Math.sqrt(tmp);
  }

  final void crossProduct(MathVector u, MathVector w)
  {
    data[0] = u.data[1] * w.data[2] - u.data[2]*w.data[1];
    data[1] = u.data[2] * w.data[0] - u.data[0]*w.data[2];
    data[2] = u.data[0] * w.data[1] - u.data[1]*w.data[0];
  }

  final void incrementalAdd(MathVector u)
  {
    for (int i = 0; i < NDIM; i++) {
      data[i] += u.data[i];
    }
  }

  final void incrementalSub(MathVector u)
  {
    for (int i = 0; i < NDIM; i++) {
      data[i] -= u.data[i];
    }
  }

  final void incrementalMultScalar(double s) 
  {
    for (int i=0; i < NDIM; i++) {
      data[i] *= s;
    }
  }

  final void incrementalDivScalar(double s)
  {
    for (int i=0; i < NDIM; i++) {
      data[i] /= s;
    }
  }

  /**
   * Add a scalar to each element in the vector and put the
   * result in this vector.
   * @param u a vector
   * @param s the scalar
   **/
  final void addScalar(MathVector u, double s) 
  {
    for (int i = 0; i < NDIM; i++) {
      data[i] = u.data[i] + s;
    }
  }


  /**
   * Return the string representation of the vector
   **/
  public String toString()
  {
    StringBuffer s = new StringBuffer();
    for (int i = 0; i < NDIM; i++) {
      s.append(data[i] + " ");
    }
    return s.toString();
  }
}