File indexing completed on 2024-04-28 03:40:44
0001 /************************************************************************************* 0002 * Copyright (C) 2010 by Aleix Pol <aleixpol@kde.org> * 0003 * Copyright (C) 2014 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or * 0006 * modify it under the terms of the GNU General Public License * 0007 * as published by the Free Software Foundation; either version 2 * 0008 * of the License, or (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 Free Software * 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 0018 *************************************************************************************/ 0019 0020 #include "matrix.h" 0021 #include "abstractexpressionvisitor.h" 0022 #include "value.h" 0023 0024 using namespace Analitza; 0025 0026 Matrix::Matrix() 0027 : Object(matrix) 0028 , m_hasOnlyNumbers(true) 0029 {} 0030 0031 Matrix::Matrix(int m, int n, const Cn* value) 0032 : Object(matrix) 0033 , m_hasOnlyNumbers(true) 0034 { 0035 Q_ASSERT(m > 0); 0036 Q_ASSERT(n > 0); 0037 Q_ASSERT(value); 0038 0039 for (int i = 0; i < m; ++i) { 0040 MatrixRow *row = new Analitza::MatrixRow(n); 0041 for (int j = 0; j < n; ++j) { 0042 row->appendBranch(value->copy()); 0043 } 0044 appendBranch(row); 0045 } 0046 } 0047 0048 Matrix::~Matrix() 0049 { 0050 qDeleteAll(m_rows); 0051 } 0052 0053 Matrix* Matrix::copy() const 0054 { 0055 Matrix* nm = new Matrix; 0056 foreach(MatrixRow* r, m_rows) { 0057 nm->appendBranch(r->copy()); 0058 } 0059 0060 return nm; 0061 } 0062 0063 bool Matrix::matches(const Object* exp, QMap< QString, const Object* >* found) const 0064 { 0065 if(Object::matrix!=exp->type()) 0066 return false; 0067 const Matrix* c=(const Matrix*) exp; 0068 if(m_rows.count()!=c->m_rows.count()) 0069 return false; 0070 0071 bool matching=true; 0072 Matrix::const_iterator it, it2, itEnd=m_rows.constEnd(); 0073 for(it=m_rows.constBegin(), it2=c->m_rows.constBegin(); matching && it!=itEnd; ++it, ++it2) { 0074 matching &= (*it)->matches(*it2, found); 0075 } 0076 0077 return matching; 0078 } 0079 0080 QVariant Matrix::accept(AbstractExpressionVisitor* exp) const 0081 { 0082 return exp->visit(this); 0083 } 0084 0085 void Matrix::appendBranch(MatrixRow* o) 0086 { 0087 Q_ASSERT(dynamic_cast<MatrixRow*>(o)); 0088 Q_ASSERT(dynamic_cast<MatrixRow*>(o)->size()>0); 0089 Q_ASSERT(m_rows.isEmpty()?true:dynamic_cast<MatrixRow*>(o)->size() == dynamic_cast<MatrixRow*>(m_rows.last())->size()); // all rows are same size 0090 0091 if (!o->hasOnlyNumbers() && m_hasOnlyNumbers) 0092 m_hasOnlyNumbers = false; 0093 0094 m_rows.append(static_cast<MatrixRow*>(o)); 0095 } 0096 0097 bool Matrix::operator==(const Matrix& m) const 0098 { 0099 bool eq = m.rowCount()==rowCount(); 0100 0101 for(int i=0; eq && i<m_rows.count(); ++i) { 0102 eq = eq && *static_cast<MatrixRow*>(m_rows[i])==*static_cast<MatrixRow*>(m.m_rows[i]); 0103 } 0104 0105 return eq; 0106 } 0107 0108 Object* Matrix::at(int i, int j) const 0109 { 0110 return m_rows.at(i)->at(j); 0111 } 0112 0113 int Matrix::columnCount() const 0114 { 0115 return m_rows.isEmpty()? 0 : static_cast<const MatrixRow*>(m_rows.first())->size(); 0116 } 0117 0118 bool Matrix::isSquare() const 0119 { 0120 return m_rows.isEmpty()? true : m_rows.size() == static_cast<const MatrixRow*>(m_rows.first())->size(); 0121 } 0122 0123 ////// MatrixRow 0124 MatrixRow::MatrixRow(int size) 0125 : Vector(Object::matrixrow, size) 0126 {} 0127 0128 QVariant MatrixRow::accept(AbstractExpressionVisitor* e) const 0129 { 0130 return e->visit(this); 0131 } 0132 0133 MatrixRow* MatrixRow::copy() const 0134 { 0135 MatrixRow *m=new MatrixRow(size()); 0136 for(MatrixRow::const_iterator it=constBegin(); it!=constEnd(); ++it) { 0137 m->appendBranch((*it)->copy()); 0138 } 0139 return m; 0140 } 0141 0142 Matrix* Matrix::identity(int n) 0143 { 0144 Q_ASSERT(n>0); 0145 0146 Analitza::Matrix *ret = new Analitza::Matrix(); 0147 0148 for (int i = 0; i < n; ++i) { 0149 MatrixRow *row = new Analitza::MatrixRow(n); 0150 for (int j = 0; j < n; ++j) { 0151 if (i == j) 0152 row->appendBranch(new Analitza::Cn(1)); 0153 else 0154 row->appendBranch(new Analitza::Cn(0)); 0155 } 0156 ret->appendBranch(row); 0157 } 0158 0159 return ret; 0160 } 0161 0162 bool Matrix::isIdentity() const 0163 { 0164 if (!hasOnlyNumbers()) 0165 return false; 0166 0167 const int nrows = m_rows.size(); 0168 0169 for (int row = 0; row < nrows; ++row) 0170 if (!m_rows.at(row)->isStandardBasisVector() || static_cast<const Cn*>(at(row, row))->value() != 1) 0171 return false; 0172 0173 return true; 0174 } 0175 0176 bool Matrix::isDiagonal() const 0177 { 0178 if (!hasOnlyNumbers()) 0179 return false; 0180 0181 const int nrows = m_rows.size(); 0182 0183 for (int row = 0; row < nrows; ++row) 0184 if (!m_rows.at(row)->isDiagonalRow()) 0185 return false; 0186 0187 return true; 0188 } 0189 0190 bool Matrix::isZero() const 0191 { 0192 bool zero = false; 0193 foreach(const MatrixRow* o, m_rows) { 0194 zero |= o->isZero(); 0195 } 0196 0197 return zero; 0198 }