package de.jungblut.math.normalize;

import de.jungblut.math.DoubleMatrix;
import de.jungblut.math.DoubleVector;
import de.jungblut.math.dense.DenseDoubleMatrix;
import de.jungblut.math.dense.DenseDoubleVector;
import de.jungblut.math.tuple.Tuple;
import de.jungblut.math.tuple.Tuple3;

public class Normalizer {

  public static Tuple<DoubleMatrix, DoubleVector> meanNormalizeRows(
      DoubleMatrix matrix) {

    DoubleVector meanVector = new DenseDoubleVector(matrix.getRowCount());

    for (int row = 0; row < matrix.getRowCount(); row++) {
      double mean = 0.0d;
      int nonZeroElements = 0;
      for (int column = 0; column < matrix.getColumnCount(); column++) {
        double val = matrix.get(row, column);
        if (val != DenseDoubleMatrix.NOT_FLAGGED) {
          mean += val;
          nonZeroElements++;
        }
      }
      if (nonZeroElements != 0.0d)
        mean = mean / nonZeroElements;
      meanVector.set(row, mean);
      for (int column = 0; column < matrix.getColumnCount(); column++) {
        double val = matrix.get(row, column);
        if (val != DenseDoubleMatrix.NOT_FLAGGED) {
          matrix.set(row, column, val - mean);
        }
      }
    }

    return new Tuple<DoubleMatrix, DoubleVector>(matrix, meanVector);
  }

  /**
   * @return the normalized (0 mean and stddev of 1) as well as the mean and the
   *         stddev.
   */
  public static Tuple3<DoubleMatrix, DoubleVector, DoubleVector> featureNormalize(
      DoubleMatrix x) {
    return featureNormalize(x, false);
  }

  /**
   * @return the normalized (0 mean and stddev of 1) as well as the mean and the
   *         stddev.
   */
  public static Tuple3<DoubleMatrix, DoubleVector, DoubleVector> featureNormalize(
      DoubleMatrix x, boolean normalizeLastColumn) {
    DenseDoubleMatrix toReturn = new DenseDoubleMatrix(x.getRowCount(),
        x.getColumnCount());
    DoubleVector meanVector = new DenseDoubleVector(x.getColumnCount());
    DoubleVector stddevVector = new DenseDoubleVector(x.getColumnCount());

    int length = x.getColumnCount();
    if (!normalizeLastColumn) {
      length = length - 1;
    }
    for (int col = 0; col < length; col++) {
      DoubleVector column = x.getColumnVector(col);
      double mean = column.sum() / column.getLength();
      meanVector.set(col, mean);
      double var = column.subtract(mean).pow(2).sum() / column.getLength();
      stddevVector.set(col, Math.sqrt(var));
    }

    for (int col = 0; col < length; col++) {
      DoubleVector column = x.getColumnVector(col)
          .subtract(meanVector.get(col)).divide(stddevVector.get(col));
      toReturn.setColumn(col, column.toArray());
    }

    return new Tuple3<DoubleMatrix, DoubleVector, DoubleVector>(toReturn,
        meanVector, stddevVector);
  }

}

@@ -1929,32 +1929,138 @@
 olumnCount());%0D%0A
+    int length = x.getColumnCount();%0D%0A    if (!normalizeLastColumn) %7B%0D%0A      length = length - 1;%0D%0A    %7D%0D%0A
     DoubleVector
@@ -2095,34 +2095,22 @@
 eVector(
-x.getColumnCount()
+length
 );%0D%0A    
@@ -2163,136 +2163,16 @@
 tor(
-x.getColumnCount());%0D%0A%0D%0A    int length = x.getColumnCount();%0D%0A    if (!normalizeLastColumn) %7B%0D%0A      length = length - 1;%0D%0A    %7D
+length);
 %0D%0A  

fix sizes