File indexing completed on 2024-05-05 05:46:11
0001 /*************************************************************************** 0002 * Copyright (C) 2003-2004 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "matrix.h" 0012 0013 #include "element.h" 0014 0015 #include <cmath> 0016 #include <iostream> 0017 0018 Matrix::Matrix(CUI n, CUI m) 0019 : m_n(n) 0020 { 0021 unsigned int size = m_n + m; 0022 0023 m_mat = new QuickMatrix(size); 0024 m_lu = new QuickMatrix(size); 0025 0026 m_y = new double[size]; 0027 m_inMap = new int[size]; 0028 0029 max_k = 0; 0030 0031 for (unsigned int i = 0; i < size; i++) 0032 m_inMap[i] = i; 0033 } 0034 0035 Matrix::~Matrix() 0036 { 0037 delete m_mat; 0038 delete m_lu; 0039 delete[] m_y; 0040 delete[] m_inMap; 0041 } 0042 0043 void Matrix::swapRows(CUI a, CUI b) 0044 { 0045 if (a == b) 0046 return; 0047 m_mat->swapRows(a, b); 0048 0049 const int old = m_inMap[a]; 0050 m_inMap[a] = m_inMap[b]; 0051 m_inMap[b] = old; 0052 0053 max_k = 0; 0054 } 0055 0056 void Matrix::performLU() 0057 { 0058 unsigned int n = m_mat->size_m(); 0059 if (n == 0) 0060 return; 0061 0062 // Copy the affected segment to LU 0063 for (uint i = max_k; i < n; i++) { 0064 for (uint j = max_k; j < n; j++) { 0065 (*m_lu)[i][j] = (*m_mat)[i][j]; 0066 } 0067 } 0068 0069 // LU decompose the matrix, and store result back in matrix 0070 for (uint k = 0; k < n - 1; k++) { 0071 double *const lu_K_K = &(*m_lu)[k][k]; 0072 unsigned foo = std::max(k, max_k) + 1; 0073 0074 // detect singular matrixes... 0075 if (std::abs(*lu_K_K) < 1e-10) { 0076 if (*lu_K_K < 0.) 0077 *lu_K_K = -1e-10; 0078 else 0079 *lu_K_K = 1e-10; 0080 } 0081 // ############# 0082 0083 for (uint i = foo; i < n; i++) { 0084 (*m_lu)[i][k] /= *lu_K_K; 0085 } 0086 0087 for (uint i = std::max(k, max_k) + 1; i < n; i++) { 0088 const double lu_I_K = (*m_lu)[i][k]; 0089 if (std::abs(lu_I_K) > 1e-12) { 0090 m_lu->partialSAF(k, i, foo, -lu_I_K); 0091 } 0092 } 0093 } 0094 0095 max_k = n; 0096 } 0097 0098 void Matrix::fbSub(QuickVector *b) 0099 { 0100 unsigned int size = m_mat->size_m(); 0101 0102 for (uint i = 0; i < size; i++) { 0103 m_y[m_inMap[i]] = (*b)[i]; 0104 } 0105 0106 // Forward substitution 0107 for (uint i = 1; i < size; i++) { 0108 double sum = 0; 0109 for (unsigned int j = 0; j < i; j++) { 0110 sum += (*m_lu)[i][j] * m_y[j]; 0111 } 0112 m_y[i] -= sum; 0113 } 0114 0115 // Back substitution 0116 m_y[size - 1] /= (*m_lu)[size - 1][size - 1]; 0117 for (int i = size - 2; i >= 0; i--) { 0118 double sum = 0; 0119 for (uint j = i + 1; j < size; j++) { 0120 sum += (*m_lu)[i][j] * m_y[j]; 0121 } 0122 m_y[i] -= sum; 0123 m_y[i] /= (*m_lu)[i][i]; 0124 } 0125 0126 // I think we don't need to reverse the mapping because we only permute rows, not columns. 0127 for (uint i = 0; i < size; i++) 0128 (*b)[i] = m_y[i]; 0129 } 0130 0131 void Matrix::displayLU() 0132 { 0133 uint n = m_mat->size_m(); 0134 for (uint _i = 0; _i < n; _i++) { 0135 uint i = m_inMap[_i]; 0136 // uint i = _i; 0137 for (uint j = 0; j < n; j++) { 0138 if (j > 0 && (*m_lu)[i][j] >= 0) 0139 std::cout << "+"; 0140 std::cout << (*m_lu)[i][j] << "(" << j << ")"; 0141 } 0142 std::cout << std::endl; 0143 } 0144 std::cout << "m_inMap: "; 0145 for (uint i = 0; i < n; i++) { 0146 std::cout << i << "->" << m_inMap[i] << " "; 0147 } 0148 std::cout << std::endl; 0149 /*cout << "m_outMap: "; 0150 for ( uint i=0; i<n; i++ ) 0151 { 0152 cout << i<<"->"<<m_outMap[i]<<" "; 0153 } 0154 cout << endl;*/ 0155 }