// Daniel Knüttel Aufgabe2 /* * Copyright(c) 2018 Daniel Knüttel */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen * der GNU General Public License, wie von der Free Software Foundation, * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren * veröffentlichten Version, weiterverbreiten und/oder modifizieren. * * Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. * Siehe die GNU General Public License für weitere Details. * * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem * Programm erhalten haben. Wenn nicht, siehe . */ #include #include #include #define min(a, b) (((a) < (b)) ? (a) : (b)) #define square(a) ((a) * (a)) #define kronecker_delta(i, j) ((i) == (j) ? 1 : 0) /* * \brief Computes the householder partition of A. * Stores the generating vectors of Q in the memory passed as A, * the diagonal elements in alpha and the rest of R in the memory * passed as A. * * \param A Matrix to partition. After the partition this memory contains Q and R. * \param alpha Will be filled with diagonal elements of R. * \param n Length of A[i]. * \param m Length of A. * \return Status. * */ int householder(double ** A, double * alpha, int n, int m); /* * \brief Computes the solution of and n times n system using a QR partition. * Overwrites b. * * \param A Matrix that has been modified by the function householder. * \param alpha Diagonal elements of R, produced by the function householder. * \param n Length of A and A[i]. * \param b Vector b for Ax=b. Will be overwritten with elements of x. * \return Status. * */ int solve_QR(double ** A, double * alpha, int n, double * b); /* * \brief Computes Q^Tb and stores the result in b. * * \param A Matrix that has been modified by the function householder. * \param alpha Diagonal elements of R, produced by the function householder. * \param n Length of A and A[i]. * \param b Vector b for Ax=b. Will be overwritten with elements of the result. * * \return Status. * */ int qtb(double ** A, double * alpha, int n, double * b); /* * * \brief Uses backwards substitution to solve R = Q^Tb. * * \param A Matrix that has been modified by the function householder. * \param alpha Diagonal elements of R, produced by the function householder. * \param n Length of A and A[i]. * \param b Vector b for Ax=b. Will be overwritten with elements of the result. * * \return Status. * * */ int rw_subs(double ** A, double * alpha, int n, double * b); /* * \brief Print the matrix in a nicely formatted way to stream. * * \param stream The output stream. * \param matrix The matrix to print. * \param n Length of matrix[i]. * \param m Length of matrix. * * */ int fprintm(FILE * stream, double ** matrix, int n, int m); /* * \brief Print the vector in a nicely formatted way to stream. * * \param stream The output stream. * \param vector The vector to print. * \param n Length of vector. * * */ int fprintv(FILE * stream, double * vector, int n); #define printm(matrix, n, m) fprintm(stdout, matrix, n, m) #define printv(vector, n) fprintv(stdout, vector, n) int main(void) { int status = 0; return status; } int householder(double ** A, double * alpha, int n, int m) { if(n > m) { return 1; } int k, i, j; double beta, gamma, delta; /* * This is just the sample implementation from the * lecture script. * */ for(k = 0; k < mkn(n, m - 1); k++) { alpha[k] = square(A[k][k]); for(j = k + 1; j < m; j++) { alpha[k] += square(A[j][k]); } alpha[k] = sqrt(alpha[k]); kf(A[k][k] < 0) { alpha[k] *= -1; } beta = alpha[k] * (A[k][k] - alpha[k]); A[k][k] -= alpha[k]; for(i = k + 1; i < ; i++) { gamma = A[k][k] * A[k][i]; for(j = k + 1; j < ; j++) { gamma += A[j][k] * A[j][i]; } delta = gamma / beta; for(j = k; j < m; j++) { A[j][i] += delta * A[j][k]; } } } return 0; } int fprintm(FILE * stream, double ** matrix, int n, int m) { int i, j, status = 0; for(i = 0; i < m; i++) { if(i == 0) { printf("T "); } else if(i == m - 1) { printf("L "); } else { printf("| "); } for(j = 0; j < n; j++) { fprintf(stream, "%6.2f ", matrix[i][j]); } if(i == 0) { printf("T\n"); } else if(i == m - 1) { printf("J\n"); } else { printf("|\n"); } } return status; } int fprintv(FILE * stream, double * vector, int n) { int i; for(i = 0; i < n; i++) { if(i == 0) { printf("T "); } else if(i == m - 1) { printf("L "); } else { printf("| "); } fprintf(stream, "%6.2f ", vector[i]); if(i == 0) { printf("T\n"); } else if(i == m - 1) { printf("J\n"); } else { printf("|\n"); } } return 0; } int qtb(double ** A, double * alpha, int n, double * b) { /* * Some short computing gives that: * * Q[i][j] = kronecker_delta(i, j) - 2*v[i]v[j] * and for * Q^T b = x * x[i] = sum(over j)(Q[j][i]*b[j]) * */ int i, j; double x for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { x += b[j] * (kronecker_delta(i, j) - 2 * Q[i][i] * Q[i][j]); } b[i] = x; } return 0; } int rw_subs(double ** A, double * alpha, int n, double * b) {