/**
  * Save the matrix to the specified file
  *
  * @param fileName - save file
  */
 public void toFile(String fileName) throws IOException {
   FileWriter out = new FileWriter(new File(fileName));
   out.write(this.rows + "\t" + this.cols + "\t" + this.totalBitsPerItem + "\n");
   Object[] rowNames = this.getRowNames().toArray();
   for (int i = 0; i < rowNames.length; i++) {
     out.write(rowNames[i].toString());
     if (i != rowNames.length - 1) out.write("\t");
   }
   out.write("\n");
   Object[] colNames = this.getColNames().toArray();
   for (int i = 0; i < colNames.length; i++) {
     out.write(colNames[i].toString());
     if (i != colNames.length - 1) out.write("\t");
   }
   out.write("\n");
   for (int i = 0; i < this.rows; i++)
     for (int j = 0; j < this.cols; j++) {
       if (this.bitCount(i, j) != 0) {
         out.write(i + "\t" + j);
         for (FlexCompRowMatrix cell : this.matrix) {
           long binVal = Double.doubleToRawLongBits(cell.get(i, j));
           /* Long.parseLong( hexString, 16) to get it back; */
           String hexString = Long.toHexString(binVal);
           out.write("\t" + hexString);
         }
         out.write("\n");
       }
     }
   out.close();
 }
 /**
  * Count the number of one-bits at the specified cell position
  *
  * @param r
  * @param c
  * @return
  */
 public int bitCount(int r, int c) {
   int bits = 0;
   if (r > this.rows || c > this.cols) return bits;
   for (FlexCompRowMatrix cell : this.matrix) {
     double val = cell.get(r, c);
     if (val != 0) bits = bits + countBits(val);
   }
   return bits;
 }
  /**
   * Constructor for FlexCompRowMatrix
   *
   * @param A Matrix to copy contents from
   * @param deep True for a deep copy, false for a reference copy. A reference copy can only be made
   *     of an <code>FlexCompRowMatrix</code>
   */
  public FlexCompRowMatrix(Matrix A, boolean deep) {
    super(A);
    rowD = new SparseVector[numRows];

    if (deep) {
      for (int i = 0; i < numRows; ++i) rowD[i] = new SparseVector(numColumns);
      set(A);
    } else {
      FlexCompRowMatrix Ar = (FlexCompRowMatrix) A;
      for (int i = 0; i < numRows; ++i) rowD[i] = Ar.getRow(i);
    }
  }
  /**
   * @param row
   * @return - array of counts of one-bits for each cell in the row.
   */
  public int[] getRowBitCount(int row) {
    int[] bits = new int[columns()];
    for (FlexCompRowMatrix cell : this.matrix) {
      SparseVector vector = cell.getRow(row);

      /*
       * Sparse vector: has indices (>0 except for first position) saying where values are; data are the values.
       */
      double[] data = vector.getData();
      int[] indices = vector.getIndex();
      for (int j = 0; j < data.length; j++) {
        if (indices[j] == 0 && j > 0) break;
        if (data[j] != 0.0) bits[indices[j]] += countBits(data[j]);
      }
    }
    return bits;
  }
  public static FlexCompRowMatrix transform(FlexCompRowMatrix a) {

    Iterator<MatrixEntry> aIt = a.iterator(); // iterating over the elements
    // in the matrix
    double ent = 0;

    while (aIt.hasNext()) {
      MatrixEntry ment = aIt.next();
      ent = ment.get();
      if (true) ent = Math.log(ent); // log transform, a good thing to do I
      // guess
      if (true) ent = Math.sqrt(ent); // this is also a valid thing to do

      a.set(ment.row(), ment.column(), ent); // Performing tranforms on
      // the matrix
    }

    return a;
  }
  /**
   * Number of ones in the entire matrix.
   *
   * @return
   */
  public long totalBitCount() {
    long result = 0L;
    for (FlexCompRowMatrix cell : this.matrix) {
      for (int j = 0; j < cols; j++) {

        SparseVector vector = cell.getRow(j);

        /*
         * Sparse vector: has indices (>0 except for first position) saying where values are; data are the
         * values.
         */
        double[] data = vector.getData();
        for (double cell2 : data) {
          result += countBits(cell2);
        }
      }
    }
    return result;
  }
  /**
   * Important method used in compute CCA
   *
   * @param X
   * @return
   */
  public static FlexCompRowMatrix computeSparseInverseSqRoot(FlexCompRowMatrix X) {

    FlexCompRowMatrix diagInvEntries = new FlexCompRowMatrix(X.numRows(), X.numColumns());

    System.out.println("++Beginning Sparse Inverse Sq. Root++");

    for (MatrixEntry e : X) {
      if (e.row() == e.column() && e.get() != 0) {
        diagInvEntries.set(e.row(), e.column(), 1 / Math.sqrt(e.get()));
      }
      if (e.row() == e.column() && e.get() == 0) {
        diagInvEntries.set(e.row(), e.column(), 10000); // Some large
        // value

      }
    }

    System.out.println("++Finished Sparse Inverse Sq. Root++");

    return diagInvEntries;
  }
  /**
   * Computing CCA
   *
   * @param xty - x = \Psi and y= \Phi
   * @param ytx
   * @param yty
   * @param xtx
   * @param svdTC
   * @param _cpcaR2
   * @param twoStageFlag
   * @return
   */
  private static void computeCCA2(
      FlexCompRowMatrix xty,
      FlexCompRowMatrix ytx,
      FlexCompRowMatrix yty,
      FlexCompRowMatrix xtx,
      SVDTemplates1 svdTC,
      ContextPCARepresentation _cpcaR2,
      int twoStageFlag,
      int hiddenStates,
      String directoryName) {

    System.out.println("+++Entering CCA Compute Function+++");
    DenseDoubleMatrix2D phiLCOLT, phiRCOLT;

    // remember x is Psi, i.e. the outside feature matrix and hence the
    // dimensionality here is dprime \times k
    System.out.println("***Creating the dense matrix, Memory Consuming Step****");

    /* Total memory currently in use by the JVM */
    System.out.println(
        "Total memory (bytes) currently used: " + Runtime.getRuntime().totalMemory());

    phiLCOLT = new DenseDoubleMatrix2D(xtx.numRows(), hiddenStates);
    /*
     * The below matrix dimensionality is d \times k
     */
    phiRCOLT = new DenseDoubleMatrix2D(yty.numRows(), hiddenStates);

    System.out.println("****Memory Consuming Step Done, Loaded two huge matrices in Memory****");

    /* Total memory currently in use by the JVM */
    System.out.println(
        "Total memory (bytes) used currently by JVM: " + Runtime.getRuntime().totalMemory());
    /*
     * dprime \times d
     */
    FlexCompRowMatrix auxMat1 = new FlexCompRowMatrix(xtx.numRows(), xty.numColumns());
    /*
     * d \times dprime
     */
    FlexCompRowMatrix auxMat2 = new FlexCompRowMatrix(yty.numRows(), ytx.numColumns());
    /*
     * dprime \times d
     */
    FlexCompRowMatrix auxMat3 = new FlexCompRowMatrix(auxMat1.numRows(), auxMat1.numColumns());
    /*
     * d \times dprime
     */
    FlexCompRowMatrix auxMat4 = new FlexCompRowMatrix(auxMat2.numRows(), auxMat2.numColumns());

    // d in our case, the dimensionality of the inside feature matrix
    int dim1 = ytx.numRows();
    // dprime in our case, the dimensionality of the outside feature matrix
    int dim2 = xty.numRows();

    System.out.println("+++Initialized auxiliary matrices+++");

    /*
     * Calculating C_{xx}^{-1|2} C_{xy}
     */
    auxMat1 =
        MatrixFormatConversion.multLargeSparseMatricesJEIGEN(computeSparseInverseSqRoot(xtx), xty);

    /*
     * Multiplying auxMat1 with C_{yy}^{-1|2}
     */
    auxMat3 =
        MatrixFormatConversion.multLargeSparseMatricesJEIGEN(
            auxMat1, computeSparseInverseSqRoot(yty));

    System.out.println("+++Computed 1 inverse+++");

    // (svdTC.computeSparseInverse(yty)).zMult(ytx, auxMat2);

    /*
     * C_{yy}^{-1|2}.C_{yx}
     */
    auxMat2 =
        MatrixFormatConversion.multLargeSparseMatricesJEIGEN(
            (svdTC.computeSparseInverseSqRoot(yty)), ytx);

    /*
     * Multiplying auxMat2 with C_{xx}^{-1|2}
     */
    auxMat4 =
        MatrixFormatConversion.multLargeSparseMatricesJEIGEN(
            auxMat2, svdTC.computeSparseInverseSqRoot(xtx));

    System.out.println("+++Computed Inverses+++");

    // auxMat1.zMult(auxMat2,auxMat3);

    System.out.println("+++Entering SVD computation+++");

    /*
     * Unnormalized Z projection matrix i.e. the Outside Projection Matrix,
     * but Unnormalized
     */
    phiLCSU =
        svdTC.computeSVD_Tropp(
            MatrixFormatConversion.createSparseMatrixCOLT(auxMat3),
            getOmegaMatrix(auxMat3.numColumns(), hiddenStates),
            dim1);

    s = svdTC.getSingularVals();

    /*
     * Write singular values to a file, just to see what's going on in here
     */
    VSMUtil.writeSingularValuesSem(s, "NNS");

    // phiL=phiLCSU;

    MatrixFormatConversion.createSparseMatrixCOLT((svdTC.computeSparseInverseSqRoot(xtx)))
        .zMult(MatrixFormatConversion.createDenseMatrixCOLT(phiLCSU), phiLCOLT);

    /*
     * This is the actual Outside projection TODO, check whether this is
     * actually the Outside projection. We get this by performing SVD on
     * C_{xx}^{-1|2}.C_{XY}.C{YY}^{-1|2}, where x is the outside feature
     * matrix (\Psi) and y is the inside feature matrix (\Phi) dprime \times
     * k
     */

    /* Total memory currently in use by the JVM */
    System.out.println(
        "Total memory (bytes) currently used: " + Runtime.getRuntime().totalMemory());

    phiL = MatrixFormatConversion.createDenseMatrixJAMA(phiLCOLT);

    /*
     * Unormalized Y projection matrix
     */
    phiRCSU =
        svdTC.computeSVD_Tropp(
            MatrixFormatConversion.createSparseMatrixCOLT(auxMat4),
            getOmegaMatrix(auxMat4.numColumns(), hiddenStates),
            dim2);

    MatrixFormatConversion.createSparseMatrixCOLT((svdTC.computeSparseInverseSqRoot(yty)))
        .zMult(MatrixFormatConversion.createDenseMatrixCOLT(phiRCSU), phiRCOLT);

    /*
     * THe inside projection matrix for the node
     */
    // 700000 \times 200

    /* Total memory currently in use by the JVM */
    System.out.println(
        "Total memory (bytes) currently used: " + Runtime.getRuntime().totalMemory());

    phiR = MatrixFormatConversion.createDenseMatrixJAMA(phiRCOLT);

    /*
     * Serialize PhiR and PhiL
     */
    System.out.println("***Serializing***");
    serializeCCAVariantsRun(directoryName);

    System.out.println("Freeing up the memory");
    phiLCOLT = null;
    phiRCOLT = null;
    phiL = null;
    phiLCSU = null;
    phiRCSU = null;
    phiR = null;

    /* Total memory currently in use by the JVM */
    System.out.println(
        "Total memory (bytes) currently used: " + Runtime.getRuntime().totalMemory());
  }
 public void reset(int r, int c) {
   for (FlexCompRowMatrix cell : this.matrix) {
     cell.set(r, c, 0);
   }
 }