public static float innerProdRowSymm(int blockLength, FSubmatrixD1 A, int rowA, FSubmatrixD1 B, int rowB, int zeroOffset) { int offset = rowA + zeroOffset; if (offset + B.col0 >= B.col1) { return(0); } if (offset < rowB) { // take in account the one in 'A' float total = B.get(offset, rowB); total += VectorOps_FDRB.dot_row_col(blockLength, A, rowA, B, rowB, offset + 1, rowB); total += VectorOps_FDRB.dot_row(blockLength, A, rowA, B, rowB, rowB, A.col1 - A.col0); return(total); } else { // take in account the one in 'A' float total = B.get(rowB, offset); total += VectorOps_FDRB.dot_row(blockLength, A, rowA, B, rowB, offset + 1, A.col1 - A.col0); return(total); } }
/** * <p> * Computes the householder vector that is used to create reflector for the column. * The results are stored in the original matrix. * </p> * * <p> * The householder vector 'u' is computed as follows:<br> * <br> * u(1) = 1 <br> * u(i) = x(i)/(τ + x(1))<br> * </p> * * The first element is implicitly assumed to be one and not written. * * @return If there was any problems or not. true = no problem. */ public static bool computeHouseHolderCol(int blockLength, FSubmatrixD1 Y, float[] gamma, int i) { float max = BlockHouseHolder_FDRB.findMaxCol(blockLength, Y, i); if (max == 0.0f) { return(false); } else { // computes tau and normalizes u by max float tau = computeTauAndDivideCol(blockLength, Y, i, max); // divide u by u_0 float u_0 = Y.get(i, i) + tau; divideElementsCol(blockLength, Y, i, u_0); gamma[Y.col0 + i] = u_0 / tau; tau *= max; // after the reflector is applied the column would be all zeros but be -tau in the first element Y.set(i, i, -tau); } return(true); }
/** * <p> * Computes the householder vector from the specified row * </p> * * <p> * The householder vector 'u' is computed as follows:<br> * <br> * u(1) = 1 <br> * u(i) = x(i)/(τ + x(1))<br> * </p> * * The first element is implicitly assumed to be one and not written. * * @return If there was any problems or not. true = no problem. */ public static bool computeHouseHolderRow(int blockLength, FSubmatrixD1 Y, float[] gamma, int i) { float max = BlockHouseHolder_FDRB.findMaxRow(blockLength, Y, i, i + 1); if (max == 0.0f) { return(false); } else { // computes tau and normalizes u by max float tau = computeTauAndDivideRow(blockLength, Y, i, i + 1, max); // divide u by u_0 float u_0 = Y.get(i, i + 1) + tau; VectorOps_FDRB.div_row(blockLength, Y, i, u_0, Y, i, i + 1, Y.col1 - Y.col0); gamma[Y.row0 + i] = u_0 / tau; // after the reflector is applied the column would be all zeros but be -tau in the first element Y.set(i, i + 1, -tau * max); } return(true); }
/** * <p> * Applies the reflectors that have been computed previously to the specified row. * <br> * A = A + u*v^T + v*u^T only along the specified row in A. * </p> * * @param blockLength * @param A Contains the reflectors and the row being updated. * @param V Contains previously computed 'v' vectors. * @param row The row of 'A' that is to be updated. */ public static void applyReflectorsToRow(int blockLength, FSubmatrixD1 A, FSubmatrixD1 V, int row) { int height = Math.Min(blockLength, A.row1 - A.row0); float[] dataA = A.original.data; float[] dataV = V.original.data; int indexU, indexV; // for each previously computed reflector for (int i = 0; i < row; i++) { int width = Math.Min(blockLength, A.col1 - A.col0); indexU = A.original.numCols * A.row0 + height * A.col0 + i * width + row; indexV = V.original.numCols * V.row0 + height * V.col0 + i * width + row; float u_row = (i + 1 == row) ? 1.0f : dataA[indexU]; float v_row = dataV[indexV]; // take in account the leading one float before = A.get(i, i + 1); A.set(i, i + 1, 1); // grab only the relevant row from A = A + u*v^T + v*u^T VectorOps_FDRB.add_row(blockLength, A, row, 1, V, i, u_row, A, row, row, A.col1 - A.col0); VectorOps_FDRB.add_row(blockLength, A, row, 1, A, i, v_row, A, row, row, A.col1 - A.col0); A.set(i, i + 1, before); } }
private void copyZeros(FSubmatrixD1 subU) { int N = Math.Min(A.blockLength, subU.col1 - subU.col0); for (int i = 0; i < N; i++) { // save the zeros for (int j = 0; j <= i; j++) { zerosM.unsafe_set(i, j, subU.get(i, j)); subU.set(i, j, 0); } // save the one if (subU.col0 + i + 1 < subU.original.numCols) { zerosM.unsafe_set(i, i + 1, subU.get(i, i + 1)); subU.set(i, i + 1, 1); } } }
public virtual bool decompose(FMatrixRBlock orig) { if (orig.numCols != orig.numRows) { throw new ArgumentException("Input matrix must be square."); } init(orig); FSubmatrixD1 subA = new FSubmatrixD1(A); FSubmatrixD1 subV = new FSubmatrixD1(V); FSubmatrixD1 subU = new FSubmatrixD1(A); int N = orig.numCols; for (int i = 0; i < N; i += A.blockLength) { // Console.WriteLine("-------- triag i "+i); int height = Math.Min(A.blockLength, A.numRows - i); subA.col0 = subU.col0 = i; subA.row0 = subU.row0 = i; subU.row1 = subU.row0 + height; subV.col0 = i; subV.row1 = height; subV.original.reshape(subV.row1, subV.col1, false); // bidiagonalize the top row TridiagonalHelper_FDRB.tridiagUpperRow(A.blockLength, subA, gammas, subV); // apply Householder reflectors to the lower portion using block multiplication if (subU.row1 < orig.numCols) { // take in account the 1 in the last row. The others are skipped over. float before = subU.get(A.blockLength - 1, A.blockLength); subU.set(A.blockLength - 1, A.blockLength, 1); // A = A + U*V^T + V*U^T multPlusTransA(A.blockLength, subU, subV, subA); multPlusTransA(A.blockLength, subV, subU, subA); subU.set(A.blockLength - 1, A.blockLength, before); } } return(true); }
public static void add_row(int blockLength, FSubmatrixD1 A, int rowA, float alpha, FSubmatrixD1 B, int rowB, float beta, FSubmatrixD1 C, int rowC, int zeroOffset, int end) { int offset = rowA + zeroOffset; if (C.col0 + offset >= C.col1) { return; } // handle leading one C.set(rowC, offset, alpha + B.get(rowB, offset) * beta); VectorOps_FDRB.add_row(blockLength, A, rowA, alpha, B, rowB, beta, C, rowC, offset + 1, end); }
/** * <p> * Final computation for a single row of 'v':<br> * <br> * v = y -(1/2)γ(y^T*u)*u * </p> * * @param blockLength * @param A * @param V * @param row * @param gamma */ public static void computeRowOfV(int blockLength, FSubmatrixD1 A, FSubmatrixD1 V, int row, float gamma) { // val=(y^T*u) float val = BlockHouseHolder_FDRB.innerProdRow(blockLength, A, row, V, row, 1); // take in account the one float before = A.get(row, row + 1); A.set(row, row + 1, 1); // v = y - (1/2)gamma*val * u VectorOps_FDRB.add_row(blockLength, V, row, 1, A, row, -0.5f * gamma * val, V, row, row + 1, A.col1 - A.col0); A.set(row, row + 1, before); }