@Override
 public void setColumnVector(int col, DoubleVector column) {
   Iterator<DoubleVectorElement> iterateNonZero = column.iterateNonZero();
   while (iterateNonZero.hasNext()) {
     DoubleVectorElement next = iterateNonZero.next();
     set(next.getIndex(), col, next.getValue());
   }
 }
 @Override
 public double sum() {
   double res = 0.0d;
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       res += e.getValue();
     }
   }
   return res;
 }
 @Override
 public DoubleMatrix divide(double scalar) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), this.getColumnCount());
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       result.set(row, e.getIndex(), e.getValue() / scalar);
     }
   }
   return result;
 }
 @Override
 public DoubleMatrix subtract(double amount) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), this.getColumnCount());
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterate = matrix.get(row).iterate();
     while (iterate.hasNext()) {
       DoubleVectorElement e = iterate.next();
       result.set(row, e.getIndex(), e.getValue() - amount);
     }
   }
   return result;
 }
 @Override
 public DoubleMatrix transpose() {
   SparseDoubleRowMatrix m = new SparseDoubleRowMatrix(this.numColumns, this.numRows);
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       m.set(e.getIndex(), row, e.getValue());
     }
   }
   return m;
 }
 @Override
 public DoubleMatrix multiplyElementWise(DoubleMatrix other) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), this.getColumnCount());
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       result.set(row, e.getIndex(), get(row, e.getIndex()) * other.get(row, e.getIndex()));
     }
   }
   return result;
 }
 @Override
 public DoubleMatrix multiply(double scalar) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this);
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       result.set(row, e.getIndex(), get(row, e.getIndex()) * scalar);
     }
   }
   return result;
 }
 @Override
 public DoubleMatrix divide(DoubleVector vec) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), this.getColumnCount());
   for (int row : this.matrix.keys()) {
     SparseDoubleVector rowVector = matrix.get(row);
     Iterator<DoubleVectorElement> iterateNonZero = rowVector.iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement next = iterateNonZero.next();
       result.set(row, next.getIndex(), next.getValue() / vec.get(row));
     }
   }
   return result;
 }
 @Override
 public DoubleVector multiplyVectorRow(DoubleVector v) {
   DoubleVector result = new SparseDoubleVector(this.getRowCount());
   for (int row : matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     double sum = 0.0d;
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       sum += (e.getValue() * v.get(e.getIndex()));
     }
     result.set(row, sum);
   }
   return result;
 }
  @Override
  public DoubleMatrix add(DoubleMatrix other) {
    SparseDoubleRowMatrix result =
        new SparseDoubleRowMatrix(other.getRowCount(), other.getColumnCount());

    for (int row : this.matrix.keys()) {
      Iterator<DoubleVectorElement> iterate = matrix.get(row).iterate();
      while (iterate.hasNext()) {
        DoubleVectorElement e = iterate.next();
        result.set(row, e.getIndex(), e.getValue() + other.get(row, e.getIndex()));
      }
    }

    return result;
  }
  @Override
  public double[][] toArray() {
    int[] rowIndices = rowIndices();
    double[][] dim = new double[getRowCount()][getColumnCount()];

    for (int row : rowIndices) {
      DoubleVector rowVector = getRowVector(row);
      Iterator<DoubleVectorElement> iterateNonZero = rowVector.iterateNonZero();
      while (iterateNonZero.hasNext()) {
        DoubleVectorElement next = iterateNonZero.next();
        dim[row][next.getIndex()] = next.getValue();
      }
    }

    return dim;
  }
 @Override
 public DoubleMatrix pow(double x) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), this.getColumnCount());
   for (int row : this.matrix.keys()) {
     Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
     while (iterateNonZero.hasNext()) {
       DoubleVectorElement e = iterateNonZero.next();
       if (x != 2d) {
         result.set(row, e.getIndex(), Math.pow(get(row, e.getIndex()), x));
       } else {
         double res = get(row, e.getIndex());
         result.set(row, e.getIndex(), res * res);
       }
     }
   }
   return result;
 }
 @Override
 public DoubleMatrix multiply(DoubleMatrix other) {
   DoubleMatrix result = new SparseDoubleRowMatrix(this.getRowCount(), other.getColumnCount());
   for (int row = 0; row < getRowCount(); row++) {
     for (int col = 0; col < other.getColumnCount(); col++) {
       double sum = 0;
       Iterator<DoubleVectorElement> kIterator = getRowVector(row).iterateNonZero();
       while (kIterator.hasNext()) {
         DoubleVectorElement k = kIterator.next();
         double val = other.get(k.getIndex(), col);
         if (val != 0d) {
           sum += k.getValue() * val;
         }
       }
       result.set(row, col, sum);
     }
   }
   return result;
 }
  @Override
  public DoubleMatrix divide(DoubleMatrix other) {
    SparseDoubleRowMatrix m = new SparseDoubleRowMatrix(other);

    for (int row : this.matrix.keys()) {
      Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
      while (iterateNonZero.hasNext()) {
        DoubleVectorElement e = iterateNonZero.next();
        m.set(row, e.getIndex(), get(row, e.getIndex()) / other.get(row, e.getIndex()));
      }
    }

    for (int col : other.columnIndices()) {
      Iterator<DoubleVectorElement> iterateNonZero = other.getColumnVector(col).iterateNonZero();
      while (iterateNonZero.hasNext()) {
        DoubleVectorElement e = iterateNonZero.next();
        m.set(e.getIndex(), col, get(e.getIndex(), col) / other.get(e.getIndex(), col));
      }
    }

    return m;
  }
 @Override
 public DoubleVector multiplyVectorColumn(DoubleVector v) {
   DoubleVector result = new SparseDoubleVector(this.getColumnCount());
   if (v.isSparse()) {
     Iterator<DoubleVectorElement> vectorNonZero = v.iterateNonZero();
     while (vectorNonZero.hasNext()) {
       DoubleVectorElement featureElement = vectorNonZero.next();
       DoubleVector rowVector = getRowVector(featureElement.getIndex());
       Iterator<DoubleVectorElement> rowNonZero = rowVector.iterateNonZero();
       while (rowNonZero.hasNext()) {
         DoubleVectorElement outcomeElement = rowNonZero.next();
         result.set(
             outcomeElement.getIndex(),
             result.get(outcomeElement.getIndex())
                 + (outcomeElement.getValue() * featureElement.getValue()));
       }
     }
   } else {
     for (int row : rowIndices()) {
       Iterator<DoubleVectorElement> iterateNonZero = matrix.get(row).iterateNonZero();
       while (iterateNonZero.hasNext()) {
         DoubleVectorElement e = iterateNonZero.next();
         result.set(e.getIndex(), (e.getValue() * v.get(row)) + result.get(e.getIndex()));
       }
     }
   }
   return result;
 }