/** * 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 = 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 (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) { 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); } }
/** * <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 (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 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); } }
/** * 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); } } }