content: /*
   *    This program is free software; you can redistribute it and/or modify
   *    it under the terms of the GNU General Public License as published by
   *    the Free Software Foundation; either version 2 of the License, or (at
   *    your option) any later version.
   *
   *    This program is distributed in the hope that it will be useful, but
   *    WITHOUT ANY WARRANTY; without even the implied warranty of
   *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *    General Public License for more details.
   *
   *    You should have received a copy of the GNU General Public License
   *    along with this program; if not, write to the Free Software
   *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  
  /*
   *    DoubleVector.java
   *    Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
   *
   */
  
  package weka.core.matrix;
  
  import weka.core.RevisionHandler;
  import weka.core.RevisionUtils;
  
  import java.lang.reflect.Method;
  import java.util.Arrays;
  
  /**
   * A vector specialized on doubles.
   * 
   * @author Yong Wang
   * @version $Revision: 5953 $
   */
  public class  DoubleVector
    implements Cloneable, RevisionHandler {
  
    double[] V; // array for internal storage of elements.
  
    private int  sizeOfVector;      // size of the vector
    
    /* ------------------------
       Constructors
       * ------------------------ */
  
    /** Constructs a null vector.
     */
    public DoubleVector() {
      this( 0 );
    }
      
    /** Constructs an n-vector of zeros. 
        @param n    length.
    */
    public DoubleVector( int n ){
      V = new double[ n ];
      setSize( n );
    }
      
    /** Constructs a constant n-vector.
        @param n    length.
        @param s    the scalar value used to fill the vector
    */
    public DoubleVector( int n, double s ){
      this( n );
      set( s );
    }
      
    /** Constructs a vector directly from a double array
     *  @param v   the array
     */
    public DoubleVector( double v[] ){
      if( v == null ) {
        V = new double[0];
        setSize( 0 );
      }
      else {
        V = v;
        setSize( v.length );
      }
    }
      
    /* ------------------------
     *  Public Methods
     * ------------------------ */
      
    /** Set a single element.
     *  @param i    Index.
     *  @param s    a[i].
     */
    public void  set( int i, double s ) {
      
      V[i] = s;
    }
      
    /** Set all elements to a value
     *  @param s    the value
     */
    public void  set( double s ) {
      set(0, size()-1, s);
    }
  
    /** Set some elements to a value
     *  @param i0 the index of the first element
     *  @param i1 the index of the second element
     *  @param s the value 
     */
    public void set( int i0, int i1, double s ) {
  
      for(int i = i0; i <= i1; i++ )
        V[i] = s;
    }
  
    /** Set some elements using a 2-D array
     *  @param i0 the index of the first element
     *  @param i1 the index of the second element
     *  @param j0 the index of the starting element in the 2-D array
     *  @param v the values
     */
    public void  set( int i0, int i1, double [] v, int j0){
      for(int i = i0; i<= i1; i++)
        V[i] = v[j0 + i - i0];
    }
      
    /** Set the elements using a DoubleVector
     *  @param v the DoubleVector
     */
    public void  set( DoubleVector v ){
      set( 0, v.size() - 1, v, 0);
    }
    
    /** Set some elements using a DoubleVector.
     *  @param i0 the index of the first element
     *  @param i1 the index of the second element
     *  @param v the DoubleVector
     *  @param j0 the index of the starting element in the DoubleVector
     */
    public void  set( int i0, int i1, DoubleVector v, int j0){
      for(int i = i0; i<= i1; i++)
        V[i] = v.V[j0 + i - i0];
    }
    
    /** Access the internal one-dimensional array.
        @return     Pointer to the one-dimensional array of vector elements.
    */
    public double []  getArray() {
      return V;
    }
      
    void  setArray( double [] a ) {
      V = a;
    }
  
    /** Returns a copy of the DoubleVector usng a double array.
        @return the one-dimensional array.  */
    public double[] getArrayCopy() {
      double v[] = new double[size()];
      
      for(int i= 0; i < size(); i++ ) 
        v[i] = V[i];
      
      return v;
    }
      
    /** Sorts the array in place */
    public void  sort() {
      Arrays.sort( V, 0, size() );
    }
  
    /** Sorts the array in place with index returned */
    public IntVector  sortWithIndex() {
      IntVector index = IntVector.seq( 0, size()-1 );
      sortWithIndex( 0, size()-1, index );
      return index;
    }
    
    /** Sorts the array in place with index changed 
     *  @param xi   first index
     *  @param xj   last index
     *  @param index array that stores all indices
     */
    public void  sortWithIndex( int xi, int xj, IntVector index ) {
      if( xi < xj ) { 
        double x, f, k;
        int xm = (int) (xi + xj) / 2; // median index
        x = Math.min( V[xi],             // median of three
  		    Math.max( V[xm], V[xj])); 
        int i = xi;
        int j = xj;
        while( i < j ) {
  	while( V[i] < x && i < xj ) i++;
  	while( V[j] > x && j > xi ) j--;
  	if( i <= j ){
  	  swap(i, j);
  	  index.swap(i, j);
  	  i++;
  	  j--;
  	}
        }
        sortWithIndex(xi, j, index);
        sortWithIndex(i, xj, index);
      }
    }
    
    /** Gets the size of the vector.
        @return     the size
    */
    public int  size(){
      return sizeOfVector;
    }
      
    /** 
     *  Sets the size of the vector
     *  @param m the size
     */ 
    public void  setSize( int m ){
      if( m > capacity() ) 
        throw new IllegalArgumentException("insufficient capacity");
      sizeOfVector = m;
    }
      
    /** Gets the capacity of the vector.
     *  @return     the capacity.
     */
    public int  capacity() {
      if( V == null ) return 0;
      return V.length;
    } 
  
    /** Sets the capacity of the vector
     *  @param n the capacity.  
     */
    public void  setCapacity ( int n ) {
      if( n == capacity() ) return;
      double [] oldV = V;
      int m = Math.min( n, size() );
      V = new double[ n ];
      setSize( m );
      set(0, m-1, oldV, 0);
    }
  
    /** Gets a single element.
     *  @param i    Index.
     *  @return     the value of the i-th element
     */
    public double  get( int i ) {
      return V[i];
    }
      
    /** 
     *  Adds a value to an element 
     *  @param i  the index of the element 
     *  @param s the value
     */
    public void  setPlus( int i, double s ) {
      V[i] += s;
    }
      
    /** 
     *  Multiplies a value to an element 
     *  @param i  the index of the element 
     *  @param s the value
     */
    public void  setTimes( int i, double s ) {
      V[i] *= s;
    }
      
    /**
     *  Adds an element into the vector
     *  @param x  the value of the new element
     */
    public void addElement( double x ) {
      if( capacity() == 0 ) setCapacity( 10 );
      if( size() == capacity() ) setCapacity( 2 * capacity() );
      V[size()] = x;
      setSize( size() + 1 );
    }
    
    /**
     *  Returns the squared vector 
     */
    public DoubleVector square() {
      DoubleVector v = new DoubleVector( size() ); 
      for(int i = 0; i < size(); i++ ) v.V[i] = V[i] * V[i];
      return v;
    }
  
    /**
     *  Returns the square-root of all the elements in the vector 
     */
    public DoubleVector sqrt() {
      DoubleVector v = new DoubleVector( size() ); 
      for(int i = 0; i < size(); i++ ) v.V[i] = Math.sqrt(V[i]);
      return v;
    }
  
    /** Makes a deep copy of the vector
     */
    public DoubleVector  copy() { 
      return (DoubleVector) clone();
    }
      
    /** Clones the DoubleVector object.
     */
    public Object  clone() { 
      int n = size();
      DoubleVector u = new DoubleVector( n );
      for( int i = 0; i < n; i++) 
        u.V[i] = V[i];
      return u;
    }
      
    /** 
     * Returns the inner product of two DoubleVectors
     * @param v the second DoubleVector
     * @return the product
     */
    public double  innerProduct(DoubleVector v) {
      if(size() != v.size()) 
        throw new IllegalArgumentException("sizes unmatch");
      double p = 0;
      for (int i = 0; i < size(); i++) {
        p += V[i] * v.V[i];
      }
      return p;
    }
      
    /** 
     * Returns the signs of all elements in terms of -1, 0 and +1.
     */
    public DoubleVector sign() 
    {
      DoubleVector s = new DoubleVector( size() );
      for( int i = 0; i < size(); i++ ) {
        if( V[i] > 0 ) s.V[i] = 1;
        else if( V[i] < 0 ) s.V[i] = -1;
        else s.V[i] = 0;
      }
      return s;
    } 
  
    /** Returns the sum of all elements in the vector.
     */
    public double  sum() 
    {
      double s = 0;
      for( int i=0; i< size(); i++) s += V[i];
      return s;
    }
      
    /** Returns the squared sum of all elements in the vector.
     */
    public double  sum2()
    {
      double s2 = 0;
      for( int i=0; i< size(); i++) s2 += V[i] * V[i];
      return s2;
    }
    
    /** Returns the L1-norm of the vector
     */
    public double norm1()
    {
      double s = 0;
      for( int i=0; i< size(); i++) s += Math.abs(V[i]);
      return s;
    }
    
    /** Returns the L2-norm of the vector
     */
    public double norm2()
    {
      return Math.sqrt( sum2() );
    }
  
    /** Returns ||u-v||^2
     *  @param v the second vector
     */
    public double sum2( DoubleVector v ) 
    {
      return minus( v ).sum2();
    }
    
    /** Returns a subvector.
     *  @param i0   the index of the first element
     *  @param i1   the index of the last element
     *  @return     v[i0:i1]
     */
    public DoubleVector  subvector( int i0, int i1 ) 
    {
      DoubleVector v = new DoubleVector( i1-i0+1 );
      v.set(0, i1 - i0, this, i0);
      return v;
    }
    
    /** Returns a subvector.
     *  @param index stores the indices of the needed elements
     *  @return     v[index]
     */
    public DoubleVector  subvector( IntVector index ) {
      DoubleVector v = new DoubleVector( index.size() );
      for( int i = 0; i < index.size(); i++ )
        v.V[i] = V[index.V[i]];
      return v;
    }
  
    /** Returns a vector from the pivoting indices. Elements not indexed are
     *  set to zero.
     *  @param index stores the pivoting indices
     *  @param length the total number of the potential elements
     *  @return the subvector */
    public DoubleVector  unpivoting( IntVector index, int length ) {
      if( index.size() > length ) 
        throw new IllegalArgumentException("index.size() > length ");
      DoubleVector u = new DoubleVector( length );
      for( int i = 0; i < index.size(); i++ ) {
        u.V[index.V[i]] =  V[i];
      }
      return u;
    }
    
    /** Adds a value to all the elements 
     *  @param x the value
     */
    public DoubleVector  plus ( double x ) {
      return copy().plusEquals( x );	
    }
    
    /** Adds a value to all the elements in place
     *  @param x the value
     */
    public DoubleVector plusEquals ( double x ) {
      for( int i = 0; i < size(); i++ )
        V[i] += x;
      return this;
    }
    
    /** 
     *  Adds another vector element by element 
     *  @param v the second vector
     */
    public DoubleVector  plus( DoubleVector v ) {
      return copy().plusEquals( v );
    }
    
    /** 
     *  Adds another vector in place element by element 
     *  @param v the second vector
     */
    public DoubleVector  plusEquals( DoubleVector v ) {
      for(int i = 0; i < size(); i++ )
        V[i] += v.V[i];
      return this;
    }
    
    /** 
     *  Subtracts a value
     *  @param x the value
     */
    public DoubleVector  minus( double x ) {
      return plus( -x );
    }
    
    /** 
     *  Subtracts a value in place
     *  @param x the value
     */
    public DoubleVector  minusEquals( double x ) {
      plusEquals( -x );
      return this;
    }
    
    /** 
     *  Subtracts another DoubleVector element by element 
     *  @param v the second DoubleVector
     */
    public DoubleVector  minus( DoubleVector v ) {
      return copy().minusEquals( v );
    }
    
    /** 
     *  Subtracts another DoubleVector element by element in place
     *  @param v the second DoubleVector
     */
    public DoubleVector  minusEquals( DoubleVector v ) {
      for(int i = 0; i < size(); i++ )
        V[i] -=  v.V[i];
      return this;
    }
      
    /** Multiplies a scalar
        @param s    scalar
        @return     s * v
    */
    public DoubleVector  times( double s ) {
      return copy().timesEquals( s );
    }
      
    /** Multiply a vector by a scalar in place, u = s * u
        @param s    scalar
        @return     replace u by s * u
    */
    public DoubleVector  timesEquals( double s ) {
      for (int i = 0; i < size(); i++) {
        V[i] *= s;
      }
      return this;
    }
      
    /** 
     *  Multiplies another DoubleVector element by element
     *  @param v the second DoubleVector
     */
    public DoubleVector  times( DoubleVector v ) {
      return copy().timesEquals( v ); 
      
    }
      
    /** 
     *  Multiplies another DoubleVector element by element in place 
     *  @param v the second DoubleVector
     */
    public DoubleVector  timesEquals( DoubleVector v ) {
      for(int i = 0; i < size(); i++ )
        V[i] *= v.V[i];
      return this;
    }
    
    /** 
     *  Divided by another DoubleVector element by element
     *  @param v the second DoubleVector
     */
    public DoubleVector  dividedBy ( DoubleVector v ) {
      return copy().dividedByEquals( v );
    }
    
    /** 
     *  Divided by another DoubleVector element by element in place 
     *  @param v the second DoubleVector
     */
    public DoubleVector  dividedByEquals ( DoubleVector v ) {
      for( int i = 0; i < size(); i++ ) {
        V[i] /= v.V[i];
      }
      return this;
    }
    
    /** 
     *  Checks if it is an empty vector
     */
    public boolean  isEmpty() {
      if( size() == 0 ) return true;
      return false;
    }
    
    /** 
     * Returns a vector that stores the cumulated values of the original
     * vector */
    public DoubleVector cumulate() 
    {
      return copy().cumulateInPlace();
    }
  	
    /** 
     * Cumulates the original vector in place 
     */
    public DoubleVector cumulateInPlace() 
    {
      for (int i = 1; i < size(); i++) {
        V[i] += V[i-1];
      }
      return this;
    }
  	
    /** 
     * Returns the index of the maximum. <p>
     * If multiple maximums exist, the index of the first is returned.
     */
    public int  indexOfMax()
    {
      int index = 0;
      double ma = V[0];
  
      for( int i = 1; i < size(); i++ ){
        if( ma < V[i] ) {
  	ma = V[i];
  	index = i;
        }
      }
      return index;
    }
    
  
    /** 
     * Returns true if vector not sorted
     */
    public boolean unsorted () {
      if( size() < 2 ) return false;
      for( int i = 1; i < size(); i++ ) {
        if( V[i-1] > V[i] )
  	return true;
      }
      return false;
    }
    
    /**
     *  Combine two vectors together
     *  @param v the second vector
     */
    public DoubleVector  cat( DoubleVector v ) {
      DoubleVector w = new DoubleVector( size() + v.size() );
      w.set(0, size() - 1, this, 0);
      w.set(size(), size() + v.size()-1, v, 0);
      return w;
    }
      
    /**
     *  Swaps the values stored at i and j
     *  @param i the index i
     *  @param j the index j
     */
    public void  swap( int i, int j ){
      if( i == j ) return;
      double t = V[i];
      V[i] = V[j];
      V[j] = t;
    }
  
    /**
     *  Returns the maximum value of all elements
     */
    public double max () {
      if( size() < 1 ) throw new IllegalArgumentException("zero size");
      double ma = V[0];
      if( size() < 2 ) return ma;
      for( int i = 1; i < size(); i++ ) {
        if( V[i] > ma ) ma = V[i];
      }
      return ma;
    }
    
  
    /**
     *  Applies a method to the vector
     *  @param className the class name
     *  @param method the method
     */
    public DoubleVector map( String className, String method ) {
      try {
        Class<?> c = Class.forName( className );
        Class [] cs = new Class[1]; 
        cs[ 0 ] = Double.TYPE;
        Method m = c.getMethod( method, cs );
        
        DoubleVector w = new DoubleVector( size() );
        Object [] obj = new Object[1];
        for( int i = 0; i < size(); i++ ) {
  	obj[0] = new Double( V[i] );
  	w.set( i, Double.parseDouble(m.invoke( null, obj ).toString()) ); 
        }
        return w;
      }
      catch ( Exception e ) {
        e.printStackTrace();
        System.exit(1);
      }
      return null;
    }
  
    /**
     * Returns the reverse vector
     */ 
    public DoubleVector  rev() {
      int n = size();
      DoubleVector w = new DoubleVector( n );
      for(int i = 0; i < n; i++ )
        w.V[i] = V[n-i-1];
      return w;
    }
    
    /**
     * Returns a random vector of uniform distribution
     * @param n the size of the vector
     */ 
    public static DoubleVector  random( int n ) {
      DoubleVector v = new DoubleVector( n );
      for (int i = 0; i < n; i++) {
        v.V[i] = Math.random();
      }
      return v;
    }
  
    /** Convert the DoubleVecor to a string
     */ 
    public String  toString() {
      return toString( 5, false );
    }
      
    /** Convert the DoubleVecor to a string
     *  @param digits the number of digits after decimal point
     *  @param trailing true if trailing zeros are to be shown
     */ 
    public String  toString( int digits, boolean trailing ) {
      if( isEmpty() ) return "null vector";
  
      StringBuffer text = new StringBuffer();
      FlexibleDecimalFormat nf = new FlexibleDecimalFormat( digits, 
  							  trailing );
      nf.grouping( true );
      for( int i = 0; i < size(); i ++ ) nf.update( V[i] );
      int count = 0;
      int width = 80;
      String number;
      for( int i = 0; i < size(); i++ ) {
        number = nf.format(V[i]);
        count += 1 + number.length();
        if( count > width-1 ) { 
  	text.append('\n'); 
  	count = 1 + number.length();
        }
        text.append( " " + number );
      }
  	
      return text.toString();
    }
    
    /**
     * Returns the revision string.
     * 
     * @return		the revision
     */
    public String getRevision() {
      return RevisionUtils.extract("$Revision: 5953 $");
    }
  
    public static void  main( String args[] ) {
  
      
      DoubleVector u = random(10);
      DoubleVector v = random(10);
      DoubleVector a = random(10);
      DoubleVector w = a; 
  
      System.out.println( random(10).plus(v).plus(w) );
  
    }
  }
  
  