/** * <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)); } } } }
//CONCURRENT_OMIT_END /** * @see CommonOps_DDRM#multTransB(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void multTransB(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numCols, B.numCols, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numRows, B.numRows); //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, xA -> { for (int xA = 0; xA < A.numRows; xA++) { int cIndex = xA * B.numRows; int aIndexStart = xA * B.numCols; int end = aIndexStart + B.numCols; int indexB = 0; for (int xB = 0; xB < B.numRows; xB++) { int indexA = aIndexStart; double total = 0; while (indexA < end) { total += A.data[indexA++] * B.data[indexB++]; } C.set(cIndex++, alpha * total); } } //CONCURRENT_ABOVE }); }
/** * @see CommonOps_DDRM#multTransA(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void multTransA_small(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numRows, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numCols, B.numCols); //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numCols, i -> { for (int i = 0; i < A.numCols; i++) { int cIndex = i * B.numCols; for (int j = 0; j < B.numCols; j++) { int indexA = i; int indexB = j; int end = indexB + B.numRows * B.numCols; double total = 0; // loop for k for (; indexB < end; indexB += B.numCols) { total += A.data[indexA] * B.data[indexB]; indexA += A.numCols; } C.set(cIndex++, alpha * total); } } //CONCURRENT_ABOVE }); }
//CONCURRENT_OMIT_BEGIN /** * @see CommonOps_DDRM#mult(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void mult_aux(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C, double[] aux) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numRows, B.numCols); if (aux == null) { aux = new double[B.numRows]; } for (int j = 0; j < B.numCols; j++) { // create a copy of the column in B to avoid cache issues for (int k = 0; k < B.numRows; k++) { aux[k] = B.unsafe_get(k, j); } int indexA = 0; for (int i = 0; i < A.numRows; i++) { double total = 0; for (int k = 0; k < B.numRows;) { total += A.data[indexA++] * aux[k++]; } C.set(i * C.numCols + j, alpha * total); } } }
/** * <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)); } } }
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> * Sets A ∈ ℜ <sup>m × n</sup> equal to an outer product multiplication of the two * vectors. This is also known as a rank-1 operation.<br> * <br> * A = x * y' * where x ∈ ℜ <sup>m</sup> and y ∈ ℜ <sup>n</sup> are vectors. * </p> * <p> * Which is equivalent to: A<sub>ij</sub> = x<sub>i</sub>*y<sub>j</sub> * </p> * * <p> * These functions are often used inside of highly optimized code and therefor sanity checks are * kept to a minimum. It is not recommended that any of these functions be used directly. * </p> * * @param x A vector with m elements. Not modified. * @param y A vector with n elements. Not modified. * @param A A Matrix with m by n elements. Modified. */ public static void outerProd(DMatrixD1 x, DMatrixD1 y, DMatrix1Row A) { int m = A.numRows; int n = A.numCols; int index = 0; for (int i = 0; i < m; i++) { double xdat = x.get(i); for (int j = 0; j < n; j++) { A.set(index++, xdat * y.get(j)); } } }
/** * @see CommonOps_DDRM#mult(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void mult_reorder(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numRows, B.numCols); if (A.numCols == 0 || A.numRows == 0) { CommonOps_DDRM.fill(C, 0); return; } int endOfKLoop = B.numRows * B.numCols; //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> { for (int i = 0; i < A.numRows; i++) { int indexCbase = i * C.numCols; int indexA = i * A.numCols; // need to assign C.data to a value initially int indexB = 0; int indexC = indexCbase; int end = indexB + B.numCols; double valA = alpha * A.data[indexA++]; while (indexB < end) { C.set(indexC++, valA * B.data[indexB++]); } // now add to it while (indexB != endOfKLoop) { // k loop indexC = indexCbase; end = indexB + B.numCols; valA = alpha * A.data[indexA++]; while (indexB < end) { // j loop C.data[indexC++] += valA * B.data[indexB++]; } } } //CONCURRENT_ABOVE }); }
//CONCURRENT_OMIT_END /** * @see CommonOps_DDRM#multTransA(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void multTransA_reorder(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numRows, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numCols, B.numCols); if (A.numCols == 0 || A.numRows == 0) { CommonOps_DDRM.fill(C, 0); return; } //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> { for (int i = 0; i < A.numCols; i++) { int indexC_start = i * C.numCols; // first assign R double valA = alpha * A.data[i]; int indexB = 0; int end = indexB + B.numCols; int indexC = indexC_start; while (indexB < end) { C.set(indexC++, valA * B.data[indexB++]); } // now increment it for (int k = 1; k < A.numRows; k++) { valA = alpha * A.unsafe_get(k, i); end = indexB + B.numCols; indexC = indexC_start; // this is the loop for j while (indexB < end) { C.data[indexC++] += valA * B.data[indexB++]; } } } //CONCURRENT_ABOVE }); }
//CONCURRENT_OMIT_BEGIN /** * @see CommonOps_DDRM#multTransAB(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row) */ public static void multTransAB_aux(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C, double[] aux) { UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'"); UtilEjml.assertShape(A.numRows, B.numCols, "The 'A' and 'B' matrices do not have compatible dimensions"); C.reshape(A.numCols, B.numRows); if (aux == null) { aux = new double[A.numRows]; } if (A.numCols == 0 || A.numRows == 0) { CommonOps_DDRM.fill(C, 0); return; } int indexC = 0; for (int i = 0; i < A.numCols; i++) { for (int k = 0; k < B.numCols; k++) { aux[k] = A.unsafe_get(k, i); } for (int j = 0; j < B.numRows; j++) { double total = 0; for (int k = 0; k < B.numCols; k++) { total += aux[k] * B.unsafe_get(j, k); } C.set(indexC++, alpha * total); } } }