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 }