File indexing completed on 2024-04-14 05:36:53

0001 /***************************************************************************
0002  *   Copyright (C) 2006 by Alan Grimes   *
0003  *   agrimes@speakeasy.net   *
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  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 
0021 //#ifndef QMATRIX_H
0022 #include "qmatrix.h"
0023 //#endif
0024 
0025 #include <cassert>
0026 #include <cmath>
0027 #include <cstdlib> // for NULL
0028 #include <cstring>
0029 #include <iostream>
0030 
0031 /*
0032 #ifndef BADRNG_H
0033 #include "badrng.h"
0034 #endif
0035 */
0036 
0037 using namespace std;
0038 
0039 // ####################################
0040 
0041 bool QuickMatrix::isSquare() const
0042 {
0043     return m == n;
0044 }
0045 
0046 // ####################################
0047 
0048 // Ideally, this should be inlined, however I am reluctant to put code in the header files which may be included in numerous
0049 // object files locations.
0050 
0051 unsigned int QuickMatrix::size_m() const
0052 {
0053     return m;
0054 }
0055 
0056 // ####################################
0057 
0058 unsigned int QuickMatrix::size_n() const
0059 {
0060     return n;
0061 }
0062 
0063 // ####################################
0064 
0065 void QuickMatrix::allocator()
0066 {
0067     //  assert(!values);
0068     assert(m);
0069     assert(n);
0070 
0071     values = new double *[m];
0072     for (unsigned int i = 0; i < m; i++) {
0073         values[i] = new double[n];
0074     }
0075 }
0076 
0077 // ####################################
0078 
0079 QuickMatrix::QuickMatrix(CUI m_in, CUI n_in)
0080     : m(m_in)
0081     , n(n_in)
0082 {
0083     allocator();
0084     fillWithZero();
0085 }
0086 
0087 // ####################################
0088 
0089 QuickMatrix::QuickMatrix(CUI m_in)
0090     : m(m_in)
0091     , n(m_in)
0092 {
0093     allocator();
0094     fillWithZero();
0095 }
0096 
0097 // ####################################
0098 
0099 QuickMatrix::QuickMatrix(const QuickMatrix *old)
0100     : m(old->m)
0101     , n(old->n)
0102 {
0103     allocator();
0104 
0105     for (unsigned int j = 0; j < m; j++) {
0106         memcpy(values[j], old->values[j], n * sizeof(double)); // fastest method. =)
0107     }
0108 }
0109 
0110 // ####################################
0111 
0112 QuickMatrix::~QuickMatrix()
0113 {
0114     for (unsigned int i = 0; i < m; i++)
0115         delete[] values[i];
0116     delete[] values;
0117 }
0118 
0119 // ####################################
0120 
0121 double QuickMatrix::at(CUI m_a, CUI n_a) const
0122 {
0123     if (m_a >= m || n_a >= n)
0124         return NAN;
0125 
0126     return values[m_a][n_a];
0127 }
0128 
0129 // ####################################
0130 
0131 bool QuickMatrix::atPut(CUI m_a, CUI n_a, const double val)
0132 {
0133     if (m_a >= m || n_a >= n)
0134         return false;
0135 
0136     values[m_a][n_a] = val;
0137     return true;
0138 }
0139 
0140 // ####################################
0141 
0142 bool QuickMatrix::atAdd(CUI m_a, CUI n_a, const double val)
0143 {
0144     if (m_a >= m || n_a >= n)
0145         return false;
0146 
0147     values[m_a][n_a] += val;
0148     return true;
0149 }
0150 
0151 // ####################################
0152 
0153 bool QuickMatrix::swapRows(CUI m_a, CUI m_b)
0154 {
0155     if (m_a >= m || m_b >= m)
0156         return false;
0157 
0158     double *temp = values[m_a];
0159     values[m_a] = values[m_b];
0160     values[m_b] = temp;
0161 
0162     return true;
0163 }
0164 
0165 // ####################################
0166 
0167 bool QuickMatrix::partialSAF(CUI m_a, CUI m_b, CUI from, const double scalor)
0168 {
0169     if (m_a >= m || m_b >= m)
0170         return false;
0171 
0172     const double *arow = values[m_a];
0173     double *brow = values[m_b];
0174 
0175     // iterate over n - m_a columns.
0176     for (unsigned int j = from; j < n; j++)
0177         brow[j] += arow[j] * scalor;
0178 
0179     return true;
0180 }
0181 
0182 // ####################################
0183 
0184 QuickVector *QuickMatrix::operator*(const QuickVector *operandvec) const
0185 {
0186     if (operandvec->size() != n)
0187         return nullptr;
0188 
0189     QuickVector *ret = new QuickVector(m);
0190 
0191     for (unsigned int i = 0; i < m; i++) {
0192         double sum = 0;
0193         for (unsigned int j = 0; j < n; j++)
0194             sum += values[i][j] * (*operandvec)[j];
0195         (*ret)[i] = sum;
0196     }
0197 
0198     return ret;
0199 }
0200 
0201 // ####################################
0202 
0203 QuickMatrix *QuickMatrix::operator+=(const QuickMatrix *operandmat)
0204 {
0205     if (operandmat->n != n || operandmat->m != m)
0206         return nullptr;
0207 
0208     for (unsigned int i = 0; i < m; i++) {
0209         for (unsigned int j = 0; j < n; j++)
0210             values[i][j] += operandmat->values[i][j];
0211     }
0212 
0213     return this;
0214 }
0215 
0216 // ####################################
0217 
0218 QuickMatrix *QuickMatrix::operator*(const QuickMatrix *operandmat) const
0219 {
0220     if (operandmat->m != n)
0221         return nullptr;
0222 
0223     QuickMatrix *ret = new QuickMatrix(m, operandmat->n);
0224 
0225     for (unsigned int i = 0; i < m; i++) {
0226         for (unsigned int j = 0; j < operandmat->n; j++) {
0227             double sum = 0;
0228             for (unsigned int k = 0; k < n; k++)
0229                 sum += values[i][k] * operandmat->values[k][j];
0230             ret->values[i][j] = sum;
0231         }
0232     }
0233 
0234     return ret;
0235 }
0236 
0237 // ###################################
0238 
0239 void QuickMatrix::dumpToAux() const
0240 {
0241     for (unsigned int j = 0; j < m; j++) {
0242         for (unsigned int i = 0; i < n; i++)
0243             cout << values[j][i] << ' ';
0244         cout << endl;
0245     }
0246 }
0247 
0248 // ###################################
0249 
0250 void QuickMatrix::fillWithZero()
0251 {
0252     for (unsigned int j = 0; j < m; j++) {
0253         memset(values[j], 0, n * sizeof(double)); // fastest method. =)
0254     }
0255 }
0256 
0257 // ###################################
0258 // sets the diagonal to a constant.
0259 QuickMatrix *QuickMatrix::operator=(const double y)
0260 {
0261     fillWithZero();
0262     unsigned int size = n;
0263     if (size > m)
0264         size = m;
0265 
0266     for (unsigned int i = 0; i < size; i++)
0267         values[i][i] = y;
0268     return this;
0269 }