/** * <p> * Performs the following operation:<br> * <br> * B = A + αI * <p> * * @param A A square matrix. Not modified. * @param B A square matrix that the results are saved to. Modified. * @param alpha Scaling factor for the identity matrix. */ public static void addIdentity(DMatrix1Row A, DMatrix1Row B, double alpha) { if (A.numCols != A.numRows) { throw new ArgumentException("A must be square"); } if (B.numCols != A.numCols || B.numRows != A.numRows) { throw new ArgumentException("B must be the same shape as A"); } int n = A.numCols; int index = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++, index++) { if (i == j) { B.set(index, A.get(index) + alpha); } else { B.set(index, A.get(index)); } } } }
/** * An alternative implementation of {@link #multTransA_small} that performs well on large * matrices. There is a relative performance hit when used on small matrices. * * @param A A matrix that is m by n. Not modified. * @param B A Vector that has length m. Not modified. * @param C A column vector that has length n. Modified. */ public static void multTransA_reorder(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (C.numCols != 1) { throw new MatrixDimensionException("C is not a column vector"); } else if (C.numRows != A.numCols) { throw new MatrixDimensionException("C is not the expected length"); } if (B.numRows == 1) { if (A.numRows != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numRows != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } if (A.numRows == 0) { CommonOps_DDRM.fill(C, 0); return; } double B_val = B.get(0); for (int i = 0; i < A.numCols; i++) { C.set(i, A.get(i) * B_val); } int indexA = A.numCols; for (int i = 1; i < A.numRows; i++) { B_val = B.get(i); for (int j = 0; j < A.numCols; j++) { C.plus(j, A.get(indexA++) * B_val); } } }
/** * <p> * Performs a matrix vector multiply.<br> * <br> * c = A * b <br> * and<br> * c = A * b<sup>T</sup> <br> * <br> * c<sub>i</sub> = Sum{ j=1:n, a<sub>ij</sub> * b<sub>j</sub>}<br> * <br> * where A is a matrix, b is a column or transposed row vector, and c is a column vector. * </p> * * @param A A matrix that is m by n. Not modified. * @param B A vector that has length n. Not modified. * @param C A column vector that has length m. Modified. */ public static void mult(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (C.numCols != 1) { throw new MatrixDimensionException("C is not a column vector"); } else if (C.numRows != A.numRows) { throw new MatrixDimensionException("C is not the expected length"); } if (B.numRows == 1) { if (A.numCols != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numCols != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } if (A.numCols == 0) { CommonOps_DDRM.fill(C, 0); return; } int indexA = 0; int cIndex = 0; double b0 = B.get(0); for (int i = 0; i < A.numRows; i++) { double total = A.get(indexA++) * b0; for (int j = 1; j < A.numCols; j++) { total += A.get(indexA++) * B.get(j); } C.set(cIndex++, total); } }
/** * <p> * Element wise p-norm:<br> * <br> * norm = {∑<sub>i=1:m</sub> ∑<sub>j=1:n</sub> { |a<sub>ij</sub>|<sup>p</sup>}}<sup>1/p</sup> * </p> * * <p> * This is not the same as the induced p-norm used on matrices, but is the same as the vector p-norm. * </p> * * @param A Matrix. Not modified. * @param p p value. * @return The norm's value. */ public static double elementP(DMatrix1Row A, double p) { if (p == 1) { return(CommonOps_DDRM.elementSumAbs(A)); } if (p == 2) { return(normF(A)); } else { double max = CommonOps_DDRM.elementMaxAbs(A); if (max == 0.0) { return(0.0); } double total = 0; int size = A.getNumElements(); for (int i = 0; i < size; i++) { double a = A.get(i) / max; total += Math.Pow(Math.Abs(a), p); } return(max * Math.Pow(total, 1.0 / p)); } }
/** * <p> * Extracts a row or column vector from matrix A. The first element in the matrix is at element (rowA,colA). * The next 'length' elements are extracted along a row or column. The results are put into vector 'v' * start at its element v0. * </p> * * @param A Matrix that the vector is being extracted from. Not modified. * @param rowA Row of the first element that is extracted. * @param colA Column of the first element that is extracted. * @param length Length of the extracted vector. * @param row If true a row vector is extracted, otherwise a column vector is extracted. * @param offsetV First element in 'v' where the results are extracted to. * @param v Vector where the results are written to. Modified. */ public static void subvector(DMatrix1Row A, int rowA, int colA, int length, bool row, int offsetV, DMatrix1Row v) { if (row) { for (int i = 0; i < length; i++) { v.set(offsetV + i, A.get(rowA, colA + i)); } } else { for (int i = 0; i < length; i++) { v.set(offsetV + i, A.get(rowA + i, colA)); } } }
/** * <p> * Performs a matrix vector multiply.<br> * <br> * C = C + A * B <br> * or<br> * C = C + A * B<sup>T</sup> <br> * <br> * c<sub>i</sub> = Sum{ j=1:n, c<sub>i</sub> + a<sub>ij</sub> * b<sub>j</sub>}<br> * <br> * where A is a matrix, B is a column or transposed row vector, and C is a column vector. * </p> * * @param A A matrix that is m by n. Not modified. * @param B A vector that has length n. Not modified. * @param C A column vector that has length m. Modified. */ public static void multAdd(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (B.numRows == 1) { if (A.numCols != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numCols != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } if (A.numRows != C.NumElements) { throw new MatrixDimensionException("C is not compatible with A"); } if (A.numCols == 0) { return; } int indexA = 0; int cIndex = 0; for (int i = 0; i < A.numRows; i++) { double total = A.get(indexA++) * B.get(0); for (int j = 1; j < A.numCols; j++) { total += A.get(indexA++) * B.get(j); } C.plus(cIndex++, total); } }
public static void setSubMatrix(DMatrix1Row src, DMatrix1Row dst, int srcRow, int srcCol, int dstRow, int dstCol, int numSubRows, int numSubCols) { for (int i = 0; i < numSubRows; i++) { for (int j = 0; j < numSubCols; j++) { double val = src.get(i + srcRow, j + srcCol); dst.set(i + dstRow, j + dstCol, val); } } }
/** * <p> * Performs a matrix vector multiply.<br> * <br> * C = C + A<sup>T</sup> * B <br> * or<br> * C = C<sup>T</sup> + A<sup>T</sup> * B<sup>T</sup> <br> * <br> * c<sub>i</sub> = Sum{ j=1:n, c<sub>i</sub> + a<sub>ji</sub> * b<sub>j</sub>}<br> * <br> * where A is a matrix, B is a column or transposed row vector, and C is a column vector. * </p> * <p> * This implementation is optimal for small matrices. There is a huge performance hit when * used on large matrices due to CPU cache issues. * </p> * * @param A A matrix that is m by n. Not modified. * @param B A vector that has length m. Not modified. * @param C A column vector that has length n. Modified. */ public static void multAddTransA_small(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (C.numCols != 1) { throw new MatrixDimensionException("C is not a column vector"); } else if (C.numRows != A.numCols) { throw new MatrixDimensionException("C is not the expected length"); } if (B.numRows == 1) { if (A.numRows != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numRows != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } int cIndex = 0; for (int i = 0; i < A.numCols; i++) { double total = 0.0; int indexA = i; for (int j = 0; j < A.numRows; j++) { total += A.get(indexA) * B.get(j); indexA += A.numCols; } C.plus(cIndex++, total); } }
private void createMinor(DMatrix1Row mat) { int w = minWidth - 1; int firstRow = (width - w) * width; for (int i = 0; i < numOpen; i++) { int col = open[i]; int srcIndex = firstRow + col; int dstIndex = i; for (int j = 0; j < w; j++) { tempMat.set(dstIndex, mat.get(srcIndex)); dstIndex += w; srcIndex += width; } } }
/** * <p> * Performs a matrix vector multiply.<br> * <br> * C = A<sup>T</sup> * B <br> * where B is a column vector.<br> * or<br> * C = A<sup>T</sup> * B<sup>T</sup> <br> * where B is a row vector. <br> * <br> * c<sub>i</sub> = Sum{ j=1:n, a<sub>ji</sub> * b<sub>j</sub>}<br> * <br> * where A is a matrix, B is a column or transposed row vector, and C is a column vector. * </p> * <p> * This implementation is optimal for small matrices. There is a huge performance hit when * used on large matrices due to CPU cache issues. * </p> * * @param A A matrix that is m by n. Not modified. * @param B A that has length m and is a column. Not modified. * @param C A column vector that has length n. Modified. */ public static void multTransA_small(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (B.numRows == 1) { if (A.numRows != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numRows != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } C.reshape(A.numCols, 1); int cIndex = 0; for (int i = 0; i < A.numCols; i++) { double total = 0.0; int indexA = i; for (int j = 0; j < A.numRows; j++) { total += A.get(indexA) * B.get(j); indexA += A.numCols; } C.set(cIndex++, total); } }
/** * An alternative implementation of {@link #multAddTransA_small} that performs well on large * matrices. There is a relative performance hit when used on small matrices. * * @param A A matrix that is m by n. Not modified. * @param B A vector that has length m. Not modified. * @param C A column vector that has length n. Modified. */ public static void multAddTransA_reorder(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C) { if (B.numRows == 1) { if (A.numRows != B.numCols) { throw new MatrixDimensionException("A and B are not compatible"); } } else if (B.numCols == 1) { if (A.numRows != B.numRows) { throw new MatrixDimensionException("A and B are not compatible"); } } else { throw new MatrixDimensionException("B is not a vector"); } if (A.numCols != C.NumElements) { throw new MatrixDimensionException("C is not compatible with A"); } int indexA = 0; for (int j = 0; j < A.numRows; j++) { double B_val = B.get(j); for (int i = 0; i < A.numCols; i++) { C.plus(i, A.get(indexA++) * B_val); } } }
/** * Computes the determinant for the specified matrix. It must be square and have * the same width and height as what was specified in the constructor. * * @param mat The matrix whose determinant is to be computed. * @return The determinant. */ public double compute(DMatrix1Row mat) { if (width != mat.numCols || width != mat.numRows) { throw new InvalidOperationException("Unexpected matrix dimension"); } // make sure everything is in the proper state before it starts initStructures(); // Array.Copy(mat.data,0,minorMatrix[0],0,mat.data.Length); int level = 0; while (true) { int levelWidth = width - level; int levelIndex = levelIndexes[level]; if (levelIndex == levelWidth) { if (level == 0) { return(levelResults[0]); } int prevLevelIndex = levelIndexes[level - 1]++; double val = mat.get((level - 1) * width + levelRemoved[level - 1]); if (prevLevelIndex % 2 == 0) { levelResults[level - 1] += val * levelResults[level]; } else { levelResults[level - 1] -= val * levelResults[level]; } putIntoOpen(level - 1); levelResults[level] = 0; levelIndexes[level] = 0; level--; } else { int excluded = openRemove(levelIndex); levelRemoved[level] = excluded; if (levelWidth == minWidth) { createMinor(mat); double subresult = mat.get(level * width + levelRemoved[level]); subresult *= UnrolledDeterminantFromMinor_DDRM.det(tempMat); if (levelIndex % 2 == 0) { levelResults[level] += subresult; } else { levelResults[level] -= subresult; } // put it back into the list putIntoOpen(level); levelIndexes[level]++; } else { level++; } } } }