+
+ /**
+ * Returns a copy in which every value in the matrix is its absolute
+ *
+ * @return
+ */
+ @Override
+ public MatrixI absolute()
+ {
+ MatrixI copy = this.copy();
+ for (int i = 0; i < copy.width(); i++)
+ {
+ double[] row = copy.getRow(i);
+ if (row != null)
+ {
+ for (int j = 0; j < row.length; j++)
+ {
+ row[j] = Math.abs(row[j]);
+ }
+ }
+ }
+ return copy;
+ }
+
+ /**
+ * Returns the mean of each row
+ *
+ * @return
+ */
+ @Override
+ public double[] meanRow()
+ {
+ double[] mean = new double[rows];
+ int i = 0;
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ mean[i++] = MiscMath.mean(row);
+ }
+ }
+ return mean;
+ }
+
+ /**
+ * Returns the mean of each column
+ *
+ * @return
+ */
+ @Override
+ public double[] meanCol()
+ {
+ double[] mean = new double[cols];
+ for (int j = 0; j < cols; j++)
+ {
+ double[] column = getColumn(j);
+ if (column != null)
+ {
+ mean[j] = MiscMath.mean(column);
+ }
+ }
+ return mean;
+ }
+
+ /**
+ * return a flattened matrix containing the sum of each column
+ *
+ * @return
+ */
+ @Override
+ public double[] sumCol()
+ {
+ double[] sum = new double[cols];
+ for (int j = 0; j < cols; j++)
+ {
+ double[] column = getColumn(j);
+ if (column != null)
+ {
+ sum[j] = MiscMath.sum(column);
+ }
+ }
+ return sum;
+ }
+
+ /**
+ * returns the mean value of the complete matrix
+ *
+ * @return
+ */
+ @Override
+ public double mean()
+ {
+ double sum = 0;
+ int nanCount = 0;
+ for (double[] row : value)
+ {
+ for (double col : row)
+ {
+ if (!Double.isNaN(col))
+ {
+ sum += col;
+ } else {
+ nanCount++;
+ }
+ }
+ }
+ return sum / (double) (this.rows * this.cols - nanCount);
+ }
+
+ /**
+ * fills up a diagonal matrix with its transposed copy
+ * !other side should be filled with 0
+ * !keeps Double.NaN found in either side
+ *
+ * TODO check on which side it was diagonal and only do calculations for the other side
+ */
+ @Override
+ public void fillDiagonal()
+ {
+ int n = this.rows;
+ int m = this.cols;
+ MatrixI copy = this.transpose(); // goes through each element in the matrix and
+ for (int i = 0; i < n; i++) // adds the value in the transposed copy to the original value
+ {
+ for (int j = 0; j < m; j++)
+ {
+ if (i != j)
+ {
+ this.addValue(i, j, copy.getValue(i,j));
+ }
+ }
+ }
+ }
+
+ /**
+ * counts the number of Double.NaN in the matrix
+ *
+ * @return
+ */
+ @Override
+ public int countNaN()
+ {
+ int NaN = 0;
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ if (Double.isNaN(this.getValue(i,j)))
+ {
+ NaN++;
+ }
+ }
+ }
+ return NaN;
+ }
+
+ /**
+ * performs an element-wise addition of this matrix by another matrix ~ this - m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI add(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't add a " + m.height() + "x" + m.width() + " to a " + this.rows + "x" + this.cols + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i,j) + m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise subtraction of this matrix by another matrix ~ this - m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI subtract(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't subtract a " + m.height() + "x" + m.width() + " from a " + this.rows + "x" + this.cols + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i,j) - m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise multiplication of this matrix by another matrix ~ this * m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI elementwiseMultiply(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't multiply a " + this.rows + "x" + this.cols + " by a " + m.height() + "x" + m.width() + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i, j) * m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise division of this matrix by another matrix ~ this / m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI elementwiseDivide(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't divide a " + this.rows + "x" + this.cols + " by a " + m.height() + "x" + m.width() + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i, j) / m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * calculate the root-mean-square for tow matrices
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public double rmsd(MatrixI m)
+ {
+ MatrixI squaredDeviates = this.subtract(m);
+ squaredDeviates = squaredDeviates.preMultiply(squaredDeviates);
+ return Math.sqrt(squaredDeviates.mean());
+ }
+
+ /**
+ * calculates the Frobenius norm of this matrix
+ *
+ * @return
+ */
+ @Override
+ public double norm()
+ {
+ double result = 0;
+ for (double[] row : value)
+ {
+ for (double val : row)
+ {
+ result += Math.pow(val, 2);
+ }
+ }
+ return Math.sqrt(result);
+ }
+
+ /**
+ * returns the sum of all values in this matrix
+ *
+ * @return
+ */
+ @Override
+ public double sum()
+ {
+ double sum = 0;
+ for (double[] row : value)
+ {
+ for (double val : row)
+ {
+ sum += (Double.isNaN(val)) ? 0.0 : val;
+ }
+ }
+ return sum;
+ }
+
+ /**
+ * returns the sum-product of this matrix with vector v
+ * @param v ~ vector
+ *
+ * @return
+ */
+ @Override
+ public double[] sumProduct(double[] v)
+ {
+ if (v.length != cols)
+ {
+ throw new IllegalArgumentException("Vector and matrix do not have the same dimension! (" + v.length + " != " + cols + ")");
+ }
+ double[] result = new double[rows];
+ for (int i = 0; i < rows; i++)
+ {
+ double[] row = value[i];
+ double sum = 0;
+ for (int j = 0; j < row.length; j++)
+ {
+ sum += row[j] * v[j];
+ }
+ result[i] = sum;
+ }
+ return result;
+ }
+
+ /**
+ * mirrors columns of the matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI mirrorCol()
+ {
+ double[][] result = new double[rows][cols];
+ for (int i = 0; i < rows; i++)
+ {
+ int k = cols - 1; // reverse col
+ for (int j = 0; j < cols; j++)
+ {
+ result[i][k--] = this.getValue(i,j);
+ }
+ }
+ MatrixI resultMatrix = new Matrix(result);
+ if (d != null)
+ resultMatrix.setD(d);
+ if (e != null)
+ resultMatrix.setE(e);
+
+ return resultMatrix;
+ }