/// <summary> /// Gram-Schmidtian orthogonalization of an m by n matrix A, such that /// {Q, R} is returned, where A = QR, Q is m by n and orthogonal, R is /// n by n and upper triangular matrix. /// </summary> /// <returns></returns> public MatrixQ[] QRGramSchmidt() { int m = rowCount; int n = columnCount; MatrixQ A = this.Clone(); MatrixQ Q = new MatrixQ(m, n); MatrixQ R = new MatrixQ(n, n); // the first column of Q equals the first column of this matrix for (int i = 1; i <= m; i++) Q[i, 1] = A[i, 1]; R[1, 1] = Complex.One; for (int k = 1; k <= n; k++) { R[k, k] = new Complex(A.Column(k).Norm()); for (int i = 1; i <= m; i++) Q[i, k] = A[i, k] / R[k, k]; for (int j = k + 1; j <= n; j++) { R[k, j] = Dot(Q.Column(k), A.Column(j)); for (int i = 1; i <= m; i++) A[i, j] = A[i, j] - Q[i, k] * R[k, j]; } } return new MatrixQ[] { Q, R }; }
/// <summary> /// Vertically concats matrices A and B, which do not have to be of the same height. /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns>Matrix [A|B]</returns> public static MatrixQ VerticalConcat(MatrixQ A, MatrixQ B) { MatrixQ C = A.Column(1); for (int j = 2; j <= A.ColumnCount; j++) { C.InsertColumn(A.Column(j), j); } for (int j = 1; j <= B.ColumnCount; j++) { C.InsertColumn(B.Column(j), C.ColumnCount + 1); } return C; }