code: package cc.mallet.types;
  
  import java.util.Random;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  
  /** 
   *  A class of static utility functions for manipulating arrays of
   *   double. 
   */
  public final class MatrixOps
  {
  
  	/** Sets every element of a double array to a given value.
  	 * @param m  The array to modify
  	 * @param v  The value
  	 */
      public static void setAll (double[] m, double v) {
  			java.util.Arrays.fill (m, v);
      }
  
      public static void set (double[] dest, double[] source) {
  			// XXX  Huh? This if-statement won't work. Java is pass-by-value, buddy. -cas
          if (source.length != dest.length)
              dest  = new double [source.length];
          System.arraycopy (source, 0, dest, 0, source.length);
      }
  
  	/**
  	 *  Multiplies every element in an array by a scalar.
  	 *  @param m The array
  	 *  @param factor The scalar
  	 */
      public static void timesEquals (double[] m, double factor) {
          for (int i=0; i < m.length; i++)
              m[i] *= factor;
      }
      
      /* Calculates the Schur/Hadamard product */ // JJW
      public static void timesEquals(double[] m1, double[] m2) {
  
          assert (m1.length == m2.length) : "unequal lengths\n";
          for (int i=0; i < m1.length; i++) {
  	    m1[i] *= m2[i];
  	}
      }
  
  	/**
  	 *  Adds a scalar to every element in an array.
  	 *  @param m The array
  	 *  @param toadd The scalar
  	 */
      public static void plusEquals (double[] m, double toadd) {
          for (int i=0; i < m.length; i++)
              m[i] += toadd;
      }
  
      public static void plusEquals (double[] m1, double[] m2) {
          assert (m1.length == m2.length) : "unequal lengths\n";
          for (int i=0; i < m1.length; i++) {
              if (Double.isInfinite(m1[i]) && Double.isInfinite(m2[i]) && (m1[i]*m2[i] < 0))
                  m1[i] = 0.0;
              else
                  m1[i] += m2[i];
          }
      }
  
      public static void plusEquals (double[] m1, double[] m2,  double factor) {
          assert (m1.length == m2.length) : "unequal lengths\n";
          for (int i=0; i < m1.length; i++) {
              double m1i = m1[i];
              double m2i = m2[i];
              if (Double.isInfinite(m1i) && Double.isInfinite(m2i) && (m1[i]*m2[i] < 0))
                  m1[i] = 0.0;
              else  m1[i] += m2[i] * factor;
          }
      }
  
    public static void plusEquals (double[][] m1, double[][] m2,  double factor)
    {
        assert (m1.length == m2.length) : "unequal lengths\n";
        for (int i=0; i < m1.length; i++) {
          for (int j=0; j < m1[i].length; j++) {
            m1[i][j] += m2[i][j] * factor;
          }
        }
    }
  
  	public static void log (double[] m)
  	{
  		for (int i = 0; i < m.length; i++)
  			m[i] = Math.log(m[i]);
  	}
  
  
      /** @deprecated  Use dotProduct() */
      public static double dot (double[] m1, double[] m2) {
          assert (m1.length == m2.length) : "m1.length != m2.length\n";
          double ret = 0.0;
          for (int i=0; i < m1.length; i++)
              ret += m1[i] * m2[i];
          return ret;
      }
  
      public static double dotProduct (double[] m1, double[] m2) {
          assert (m1.length == m2.length) : "m1.length != m2.length\n";
          double ret = 0.0;
          for (int i=0; i < m1.length; i++)
              ret += m1[i] * m2[i];
          return ret;
      }
  
      public static double absNorm (double[] m) {
          double ret = 0;
          for (int i = 0; i < m.length; i++)
              ret += Math.abs(m[i]);
          return ret;
      }
  
      public static double twoNorm (double[] m) {
          double ret = 0;
          for (int i = 0; i < m.length; i++)
              ret += m[i] * m[i];
          return Math.sqrt (ret);
      }
  
      public static double twoNormSquared (double[] m) {
        double ret = 0;
        for (int i = 0; i < m.length; i++)
            ret += m[i] * m[i];
        return ret;
    }
  
      public static double oneNorm (double[] m) {
          double ret = 0;
          for (int i = 0; i < m.length; i++)
              ret += m[i];
          return ret;
      }
      
      public static double oneNormalize (double[] m) {
      	double sum = oneNorm(m);
      	for (int i = 0; i < m.length; i++)
      		m[i] /= sum;
      	return sum;
      }
      
      public static double normalize (double[] m) {
      	return oneNormalize(m);
      }
  
      public static double infinityNorm (double[] m) {
          double ret = Double.NEGATIVE_INFINITY;
          for (int i = 0; i < m.length; i++)
              if (Math.abs(m[i]) > ret)
                  ret = Math.abs(m[i]);
          return ret;
      }
  
      public static double absNormalize (double[] m) {
          double norm = absNorm(m);
          if (norm > 0)
              for (int i = 0; i < m.length; i++)
                  m[i] /= norm;
          return norm;
      }
  
      public static double twoNormalize (double[] m) {
          double norm = twoNorm(m);
          if (norm > 0)
              for (int i = 0; i < m.length; i++)
                  m[i] /= norm;
          return norm;
      }
  
      public static void substitute (double[] m, double oldValue, double newValue) {
          for (int i = m.length-1; i >= 0; i--)
              if (m[i] == oldValue)
                  m[i] = newValue;
      }
  
      /** If "ifSelected" is false, it reverses the selection.  If
       "fselection" is null, this implies that all features are
       selected; all values in the row will be changed unless
       "ifSelected" is false. */
      public static final void rowSetAll (double[] m, int nc, int ri, double v, FeatureSelection fselection, boolean ifSelected) {
          if (fselection == null) {
              if (ifSelected == true) {
                  for (int ci = 0; ci < nc; ci++)
                      m[ri*nc+ci] = v;
              }
          } else {
              // xxx Temporary check for full selection
              //assert (fselection.nextDeselectedIndex (0) == nc);
              for (int ci = 0; ci < nc; ci++)
                  if (fselection.contains(ci) ^ !ifSelected)
                      m[ri*nc+ci] = v;
          }
      }
  
      public static double rowDotProduct (double[] m, int nc, int ri,
                                          Vector v, int maxCi,
                                          FeatureSelection selection) {
          return rowDotProduct (m, nc, ri, v, 1, maxCi, selection);
      }
  
      public static double rowDotProduct (double[] m, int nc, int ri,
                                          Vector v, double factor, int maxCi,
                                          FeatureSelection selection) {
          double ret = 0;
          if (selection != null) {
    					int size = v.numLocations();
              for (int cil = 0; cil < size; cil++) {
                  int ci = v.indexAtLocation (cil);
                  if (selection.contains(ci) && ci < nc && ci <= maxCi)
                      ret += m[ri*nc+ci] * v.valueAtLocation(cil) * factor;
              }
          } else {
  					int size = v.numLocations();
  					for (int cil = 0; cil < size; cil++) {
  						int ci = v.indexAtLocation (cil);
              if (ci <= maxCi)
  						  ret += m[ri*nc+ci] * v.valueAtLocation(cil) * factor;
  					}
          }
          return ret;
      }
  
      public static final void rowPlusEquals (double[] m, int nc, int ri,
                                              Vector v, double factor) {
          for (int vli = 0; vli < v.numLocations(); vli++)
              m[ri*nc+v.indexAtLocation(vli)] += v.valueAtLocation(vli) * factor;
  
      }
  
      public static boolean isNaN(double[] m) {
          for (int i = 0; i < m.length; i++)
              if (Double.isNaN(m[i]))
                  return true;
          return false;
      }
  
      // gsc: similar to isNan, but checks for inifinite values
      public static boolean isInfinite(double[] m) {
      		for (int i = 0; i < m.length; i++)
      				if (Double.isInfinite(m[i]))
      						return true;
      		return false;
      }
      
      // gsc: returns true if any value in the array is either NaN or infinite
      public static boolean isNaNOrInfinite(double[] m) {
      		for (int i = 0; i < m.length; i++)
      				if (Double.isInfinite(m[i]) || Double.isNaN(m[i]))
      						return true;
      		return false;
      }
      
      // gsc: returns true if any value in the array is greater than 0.0/-0.0
      public static boolean isNonZero(double[] m) {
      		for (int i = 0; i < m.length; i++)
      				if (Math.abs(m[i]) > 0.0)
      						return true;
      		return false;
      }
      
      // gsc: returns true if any value in the array is 0.0/-0.0
      public static boolean isZero(double[] m) {
      		for (int i = 0; i < m.length; i++)
      				if (Math.abs(m[i]) == 0.0)
      						return true;
      		return false;
      }
      
      // TODO: This is the same as oneNorm(), and should be removed
      public static double sum (double[] m) {
          double sum = 0;
          for (int i = 0; i < m.length; i++)
              sum += m[i];
          return sum;
      }
  
      public static double sum (double[][] m) {
          double sum = 0;
          for (int i = 0; i < m.length; i++)
            for (int j = 0; j < m[i].length; j++)
              sum += m[i][j];
          return sum;
      }
  
      public static int sum (int[] m) {
          int sum = 0;
          for (int i = 0; i < m.length; i++)
              sum += m[i];
          return sum;
      }
  
      // CPAL
  		// TODO: This should be removed, because FeatureVector already has oneNorm(). -AKM
      public static double sum(Vector v) {
          double sum = 0;
          for (int vli = 0; vli < v.numLocations(); vli++) {
              sum = sum +  v.valueAtLocation(vli);
          }
          return sum;
      }
  
      public static double mean (double[] m) {
          double sum = 0;
          for (int i = 0; i < m.length; i++)
              sum += m[i];
          return sum / m.length;
      }
  
      /** Return the standard deviation */
      public static double stddev (double[] m) {
          double mean = mean (m);
          double s = 0;
          for (int i = 0; i < m.length; i++)
              s += (m[i] - mean) * (m[i] - mean);
          return Math.sqrt (s/m.length);
          // Some prefer dividing by (m.length-1), but this is also common
      }
  
      public static double stderr (double[] m ) {
          return stddev(m) / Math.sqrt (m.length);
      }
  
      // gsc
      /** Return the variance */
      public static double variance (double[] m) {
          double mean = mean (m);
          double s = 0;
          for (int i = 0; i < m.length; i++)
              s += (m[i] - mean) * (m[i] - mean);
          return s/m.length;
          // Some prefer dividing by (m.length-1), but this is also common
      }
  
    /**
     * Prints a double array to standard output
     * @param m Array to print.
     */
      public static final void print (double[] m)
      {
        print (new PrintWriter (new OutputStreamWriter (System.out), true), m);
      }
  
      /**
       * Prints a double array to the given PrintWriter.
       * @param out Writer to print ouput to
       * @param m Array to print.
       */
        public static final void print (PrintWriter out, double[] m)
      {
        for (int i = 0; i < m.length; i++) {
          out.print (" " + m[i]);
        }
        out.println("");
      }
  
      public static final void print (double[][] arr)
      {
        for (int i = 0; i < arr.length; i++) {
          double[] doubles = arr[i];
          print (doubles);
        }
      }
  
      /** Print a space-separated array of elements
       * 
       * @param m An array of any type
       */
      public static final String toString( Object m ) {
  	StringBuffer sb = new StringBuffer();
  	
  	int n=java.lang.reflect.Array.getLength(m)-1;
  	for (int i = 0; i<n ; i++) {
  	    sb.append(java.lang.reflect.Array.get(m,i));
  	    sb.append(" ");
  	}
  
  	if (n>=0)
  	    sb.append(java.lang.reflect.Array.get(m,n));
  
  	return sb.toString();
      }
  
    public static final void printInRows (double[] arr)
    {
      for (int i = 0; i < arr.length; i++) {
        double v = arr[i];
        System.out.println("["+i+"]  "+arr[i]);
      }
    }
  
    public static void setAll (double[][][] m, double v)
    {
      for (int i = 0; i < m.length; i++) {
        for (int j = 0; j < m[i].length; j++) {
          for (int k = 0; k < m[i][j].length; k++) {
            m[i][j][k] = v;
          }
        }
      }
    }
  
    public static void setAll (double[][] m, double v)
    {
      for (int i = 0; i < m.length; i++) {
        for (int j = 0; j < m[i].length; j++) {
          m[i][j] = v;
        }
      }
    }
  
    public static void print (int[][] arr)
    {
      for (int i = 0; i < arr.length; i++) {
        print (arr [i]);
      }
    }
  
    public static void print (int[] m)
    {
      for (int i = 0; i < m.length; i++) {
           System.out.print (" " + m[i]);
       }
       System.out.println("");
    }
  
  
    public static double[] randomVector (int n, Random r)
    {
      double[] ret = new double [n];
      for (int i = 0; i < n; i++) ret[i] = r.nextDouble ();
      return ret;
    }
  
    public static void timesEquals (double[][] m, double factor)
    {
      for (int i = 0; i < m.length; i++) {
        for (int j = 0; j < m[i].length; j++) {
          m[i][j] *= factor;
        }
      }
    }
  
    /**
     * Returns the maximum elementwise absolute difference between two vectors.
     *   This is the same as infinityNorm (v1 - v2) (if that were legal Java).
     * @param v1 Input vector, as double[]
     * @param v2 Input vector, as double[]
     * @return
     */
  
    public static double maxAbsdiff (double[] v1, double[] v2)
    {
      double max = Double.NEGATIVE_INFINITY;
      for (int i = 0; i < v1.length; i++) {
        double val = Math.abs (v1[i] - v2[i]);
        if (val > max) max = val;
      }
      return max;
    }
  
    public static int max (int[][] m) {
      int maxval = m[0][0];
      for (int i=0; i < m.length; i++) {
        for (int j=0; j < m[i].length; j++) {
          if (m[i][j] > maxval) {
            maxval = m[i][j];
          }
        }
      }
      return maxval;
    } 
  
    public static int max (int [] elems)
    {
      int max = Integer.MIN_VALUE;
      for (int i = 0; i < elems.length; i++) {
        int elem = elems[i];
        if (elem > max) {
          max = elem;
        }
      }
      return max;
    }
  
    public static double max (double [] elems)
    {
      double max = Double.NEGATIVE_INFINITY;
      for (int i = 0; i < elems.length; i++) {
        double elem = elems[i];
        if (elem > max) {
          max = elem;
        }
      }
      return max;
    }
    
    public static double min (double [] elems)
    {
      double min = Double.POSITIVE_INFINITY;
      for (int i = 0; i < elems.length; i++) {
        double elem = elems[i];
        if (elem < min) {
          min = elem;
        }
      }
      return min;
    }
    
    public static int maxIndex (double [] elems)
    {
      double max = Double.NEGATIVE_INFINITY;
      int maxIndex = -1; 
      for (int i = 0; i < elems.length; i++) {
        double elem = elems[i];
        if (elem > max) {
          max = elem;
          maxIndex = i;
        }
      }
      return maxIndex;
    }
    
    public static int minIndex (double [] elems)
    {
      double min = Double.POSITIVE_INFINITY;
      int minIndex = -1; 
      for (int i = 0; i < elems.length; i++) {
        double elem = elems[i];
        if (elem < min) {
          min = elem;
          minIndex = i;
        }
      }
      return minIndex;
    }
    
    public static double[] append (double[] original, double newValue)
    {
    	double[] ret = new double[original.length + 1];
  		System.arraycopy(original, 0, ret, 0, original.length);
  		ret[original.length] = newValue;
    	return ret;
    }
  
  	public static double max(double[][] ds) {
  		double max = Double.NEGATIVE_INFINITY;
  		for (int i = 0; i < ds.length; i++) {
  			for (int j = 0; j < ds[i].length; j++) {
  				if (ds[i][j] > max) {
  					max = ds[i][j];
  				}
  			}
  		}
  		return max;
  	}
  	
  	public static int[] maxIndex(double[][] ds) {
  		int[] maxIndices = new int[] {-1,-1};
  		double max = Double.NEGATIVE_INFINITY;
  		for (int i = 0; i < ds.length; i++) {
  			for (int j = 0; j < ds[i].length; j++) {
  				if (ds[i][j] > max) {
  					max = ds[i][j];
  					maxIndices[0] = i;
  					maxIndices[1] = j;
  				}
  			}
  		}
  		return maxIndices;
  	}
  
    public static void expNormalize(double[] scores) {
      double max = MatrixOps.max (scores);
      double sum = 0;
      for (int i = 0; i < scores.length; i++)
        sum += (scores[i] = Math.exp (scores[i] - max));
      for (int i = 0; i < scores.length; i++) 
        scores[i] /= sum;
    }
  }
  
  
  