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 }