Note, in Ktechlab there is a class Matrix *AND* a class matrix. =P

the issue I have with how they're done is that the matrix implementation
is more than a bit messy and it uses a list of vectors internally,
vectors are a fairly heavy-weight objects in themselves and this adds
overhead.

This is a set of matrix and vector classes I develed for a class I was
taking. I thought I could just drop them into ktechlab... Well, they
were written using Smalltalk conventions while Ktechlab uses C++
conventions... It took several days to do it....

Go ahead and make a "math" subdirectory for the project and put these in
it. Remove the classes matrix and Vector and use these instead.

They have a number of methods which should be helpful in cleaning up the
code of Matrix and elsewhere.

I have been using these in my own fork... This is part of the task of
reconciling the changes...

-- 
Opera: Sing it loud! :o(  )>-<
/***************************************************************************
 *   Copyright (C) 2006 by Alan Grimes   *
 *   [EMAIL PROTECTED]   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef QMATRIX_H
#define QMATRIX_H

#ifndef QVECTOR_H
#include "qvector.h"
#endif

class QuickMatrix {
public :
         QuickMatrix(CUI m_in, CUI n_in);
         QuickMatrix(CUI m_in);
         QuickMatrix(const QuickMatrix *old); // ye olde copy constructor.
        ~QuickMatrix();

// accessors
// we use accessors so that we can provide range checking.
// we use Smalltalk style naming conventions.
        double at(CUI m_a, CUI n_a) const;
        bool atPut(CUI m_a, CUI n_a, const double val);
        bool atAdd(CUI m_a, CUI n_a, const double val); // just give a negative 
val to subtract. =)

        bool isSquare() const;

        double *&operator[]( const int i) { return values[i]; }
        const double *operator[]( const int i) const { return values[i]; }

        unsigned int size_m() const;
        unsigned int size_n() const;

// functions for some elementary row operations.
// these are actually procedures because they operate on the current matrix 
rather than
// producing a results matrix.  
        bool scaleRow(CUI m_a, const double scalor);
                // changes B by adding A.
        bool addRowToRow(CUI m_a, CUI m_b);
                // changes B by adding the result of A times a scalor 
        bool scaleAndAdd(CUI m_a, CUI m_b, const double scalor);
        bool partialScaleAndAdd(CUI m_a, CUI m_b, const double scalor);
        bool partialSAF(CUI m_a, CUI m_b, CUI from, const double scalor);
        bool swapRows(CUI m_a, CUI m_b);

// functions that accelerate certain types of
// operations that would otherwise require millions of at()'s
        double multstep(CUI row, CUI pos, CUI col) const;
        double multRowCol(CUI row, CUI col, CUI lim) const;

        QuickMatrix *transposeSquare() const; // Multiplies self by transpose.
        QuickVector *transposeMult(const QuickVector *operandvec) const;

// utility functions:
        void fillWithRandom();
        void fillWithZero();
        double rowsum(CUI m);
        double absrowsum(CUI m);
        QuickVector *normalizeRows();

// Matrix arithmetic.
        QuickMatrix *operator +=(const QuickMatrix *othermat);
        QuickMatrix *operator *=(const double y);
        QuickMatrix *operator =(const double y); // sets the diagonal to a 
constant.
        QuickMatrix *operator =(const QuickMatrix *oldmat);
        QuickVector *operator *(const QuickVector *operandvec) const;
        QuickMatrix *operator *(const QuickMatrix *operandmat) const;

// debugging
        void dumpToAux() const;

private :
// We don't have a default matrix size so therefore we lock the default 
constructor. 
        QuickMatrix() {};

        void allocator();

        unsigned int m, n;
        double **values;
};

#endif
/***************************************************************************
 *   Copyright (C) 2006 by Alan Grimes   *
 *   [EMAIL PROTECTED]   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <cstdlib> // for null 
#include <cmath>
#include <cassert>
#include <kdebug.h>
#include <iostream>

using namespace std;
using namespace std;

#ifndef QVECTOR_H
#include "qvector.h"
#endif

/*
#ifndef BADRNG_H
#include "badrng.h"
#endif
*/

// ######################################

unsigned int QuickVector::size() const {
        return m;
}

// ######################################

double QuickVector::at(CUI m_a) const {
//      if(!m_a || m_a > m) return NAN;

        return values[m_a];
}

// #####################################

bool QuickVector::atPut(CUI m_a, const double val) {
        if(m_a >= m) return false;

        values[m_a] = val;
        changed = true;
        return true;
}

// #####################################

bool QuickVector::atAdd(CUI m_a, const double val) {
        if(m_a >= m) return false;

        values[m_a] += val;
        changed = true;
        return true;
}

// #####################################

QuickVector::QuickVector(CUI m_in)
        : m(m_in), changed(true)
{
        assert(m);
        values = new double[m];
        memset(values, 0, sizeof(double) *m);
}

// #####################################

QuickVector::QuickVector(const QuickVector *old)
        : m(old->m), changed(old->changed) {
        assert(m);
        values = new double[m];

        for(unsigned int j = 0; j < m; j++) 
                values[j] = old->values[j];
}

// #####################################

QuickVector::~QuickVector() {
        delete values;
}

// #####################################

/*
void QuickVector::fillWithRandom() {
        for(unsigned int j = 0; j < m; j++)
                values[j] = drng();
}
*/

// #####################################

void QuickVector::fillWithZeros() {
        memset(values, 0, m*sizeof(double));
        changed = true;
}

// #####################################

QuickVector *QuickVector::operator-(const QuickVector *y) const {
        if(y->m != m) return NULL;

        QuickVector *ret;
        ret = new QuickVector(m);

        for(unsigned int i = 0; i < m; i++) ret->values[i] = values[i] - 
y->values[i];

        return ret;
}

// ####################################

void QuickVector::dumpToAux() const {
        for(unsigned int i = 0; i < m; i++) cout << values[i] << ' ';
        cout << endl;
}

// ####################################

bool QuickVector::swapElements(CUI m_a, CUI m_b) {
        if(m_a >= m || m_b >= m) return false;

        double temp = values[m_a];
        values[m_a] = values[m_b];
        values[m_b] = temp;
        changed = true;

        return true;
}

// ###################################

QuickVector *QuickVector::operator *=(const QuickVector *y) {
        if(y->m != m) return NULL;

        for(unsigned int i = 0; i < m; i++) values[i] *= y->values[i];
        changed = true;
        return this;
}

// ###################################

QuickVector *QuickVector::operator +=(const QuickVector *y) {
        if(y->m != m) return NULL;

        for(unsigned int i = 0; i < m; i++) values[i] += y->values[i];
        changed = true;
        return this;
}

// ###################################

/***************************************************************************
 *   Copyright (C) 2006 by Alan Grimes   *
 *   [EMAIL PROTECTED]   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *(at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef QVECTOR_H
#define QVECTOR_H

#ifndef CUI
#define CUI     const unsigned int
#endif

#define EPSILON 0.000001

class QuickVector {
public :
         QuickVector(CUI m_in);
        ~QuickVector();
         QuickVector(const QuickVector *old); // ye olde copy constructor.

        double & operator[]( const int i) { changed = true; return values[i]; }
        const double operator[]( const int i) const { return values[i]; }

// accessors
// we use accessors so that we can provide range checking.
// we use Smalltalk style naming conventions.
        double at(CUI m_a) const;
        bool atPut(CUI m_a, const double val);
        bool atAdd(CUI m_a, const double val);

        unsigned int size() const;

// utility functions:
//      void fillWithRandom();
        void fillWithZeros();
        bool swapElements(CUI m_a, CUI m_b);

// Vector arithmetic.

        QuickVector *operator*=(const double *y);
        QuickVector *operator*=(const QuickVector *y);
        QuickVector *operator+=(const QuickVector *y);
        QuickVector *operator-(const QuickVector *y) const;

// debugging
        void dumpToAux() const;

        /**
         * Returns true if the vector has changed since setUnchanged was last 
called
         */
        inline bool isChanged() const { return changed; }
        /**
         * Sets the changed status to false.
         */
        inline void setUnchanged() { changed=false; }

private :
// We don't have a default vector size so therefore we lock the default 
constructor.
        QuickVector() {};
        unsigned int m;
        bool changed;
        double *values;
};

#endif
/***************************************************************************
 *   Copyright (C) 2006 by Alan Grimes   *
 *   [EMAIL PROTECTED]   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <cstdlib> // for NULL
#include <cmath>
#include <cassert>
#include <iostream>

using namespace std;

#ifndef QMATRIX_H
#include "qmatrix.h"
#endif

/*
#ifndef BADRNG_H
#include "badrng.h"
#endif
*/

// ####################################

bool QuickMatrix::isSquare() const {
        return m == n;
} 

// ####################################

// Ideally, this should be inlined, however I am reluctant to put code in the 
header files which may be included in numerous
// object files locations.

unsigned int QuickMatrix::size_m() const {
        return m;
}

// ####################################

unsigned int QuickMatrix::size_n() const {
        return n;
}

// ####################################

void QuickMatrix::allocator() {
//      assert(!values);
        assert(m);
        assert(n);

        values = new double*[m];
        for(unsigned int i = 0; i < m; i++) {
                values[i] = new double[n];
        }
}

// ####################################

QuickMatrix *QuickMatrix::transposeSquare() const {
        QuickMatrix *newmat = new QuickMatrix(n);

        for(unsigned int i= 0; i < n; i++) {
                for(unsigned int j = 0; j < n; j++) {
                        newmat->values[i][j] = 0;
                        for(unsigned int k = 0; k < m; k++) {
                                newmat->values[i][j] += values[k][i] * 
values[k][j];
                        }
                }
        }

        return newmat;
}

// #####################################

QuickVector *QuickMatrix::transposeMult(const QuickVector *operandvec) const {
        if(operandvec->size() != m) return NULL;

        QuickVector *ret = new QuickVector(n);

        for(unsigned int i = 0; i < n; i++) {
                double sum = 0;
                for(unsigned int j = 0; j < m; j++)
                        sum += values[j][i] * (*operandvec)[j];
                (*ret)[i] = sum;
        }

        return ret;
}

// ####################################

QuickMatrix::QuickMatrix(CUI m_in, CUI n_in)
        : m(m_in), n(n_in) {
        allocator();
        fillWithZero();
}

// ####################################

QuickMatrix::QuickMatrix(CUI m_in)
        : m(m_in), n(m_in) {
        allocator();
        fillWithZero();
}

// ####################################

QuickMatrix::QuickMatrix(const QuickMatrix *old)
        : m(old->m), n(old->n) {
        allocator();

        for(unsigned int j = 0; j < m; j++) {
                memcpy(values[j], old->values[j], n*sizeof(double)); // fastest 
method. =)
        }
}

// ####################################

QuickMatrix::~QuickMatrix() {
        for(unsigned int i = 0; i < m; i++) delete values[i];
        delete values;
}

// ####################################

double QuickMatrix::at(CUI m_a, CUI n_a) const
{
        if(m_a >= m || n_a >= n) return NAN;

        return values[m_a][n_a];
}

// ####################################

double QuickMatrix::multstep(CUI row, CUI pos, CUI col) const
{
        return values[row][pos] * values[pos][col];
}

// ####################################

double QuickMatrix::multRowCol(CUI row, CUI col, CUI lim) const
{
        const double *rowVals = values[row];

        double sum = 0;
        for(unsigned int i = 0; i < lim; i++)
                sum += rowVals[i] * values[i][col];
        return sum;
}

// ####################################

bool QuickMatrix::atPut(CUI m_a, CUI n_a, const double val) {
        if(m_a >= m || n_a >= n) return false;

        values[m_a][n_a] = val;
        return true;
}

// ####################################

bool QuickMatrix::atAdd(CUI m_a, CUI n_a, const double val) {
        if(m_a >= m || n_a >= n) return false;

        values[m_a][n_a] += val;
        return true;
}

// ####################################

bool QuickMatrix::swapRows(CUI m_a, CUI m_b) {
        if(m_a >= m || m_b >= m) return false;

        double *temp = values[m_a];
        values[m_a] = values[m_b];
        values[m_b] = temp;

        return true;
}

// ####################################

bool QuickMatrix::scaleRow(CUI m_a, const double scalor) {
        if(m_a >= m) return false;

        double *arow = values[m_a];

// iterate over n columns. 
        for(unsigned int j = 0; j < n; j++) arow[j] *= scalor;

        return true;
}

// ####################################

double QuickMatrix::rowsum(CUI m) {
        if(m >= m) return NAN;

        double *arow = values[m];

        double sum = 0.0;

// iterate over n columns. 
        for(unsigned int j = 0; j < n; j++) sum += arow[j];

        return sum;
}

// ####################################

double QuickMatrix::absrowsum(CUI m) {
        if(m >= m) return NAN;

        double *arow = values[m];

        double sum = 0.0;

// iterate over n columns. 
        for(unsigned int j = 0; j < n; j++) sum += fabs(arow[j]);

        return sum;
}

// ####################################

// behaves oddly but doesn't crash if m_a == m_b
bool QuickMatrix::scaleAndAdd(CUI m_a, CUI m_b, const double scalor) {
        if(m_a >= m || m_b >= m) return false;

        const double *arow = values[m_a];
        double *brow = values[m_b];

// iterate over n columns. 
        for(unsigned int j = 0; j < n; j++)
                brow[j] += arow[j] * scalor;

        return true;
}

// ####################################

// behaves oddly but doesn't crash if m_a == m_b
bool QuickMatrix::partialScaleAndAdd(CUI m_a, CUI m_b, const double scalor) {
        if(m_a >= m || m_b >= m) return false;

        const double *arow = values[m_a];
        double *brow = values[m_b];

// iterate over n - m_a columns.
        for(unsigned int j = m_a; j < n; j++)
                brow[j] += arow[j] * scalor;

        return true;
}

// ########################################

bool QuickMatrix::partialSAF(CUI m_a, CUI m_b, CUI from, const double scalor) {
        if(m_a >= m || m_b >= m) return false;

        const double *arow = values[m_a];
        double *brow = values[m_b];

// iterate over n - m_a columns.
        for(unsigned int j = from; j < n; j++)
                brow[j] += arow[j] * scalor;

        return true;
}

// ####################################
/*
void QuickMatrix::fillWithRandom() {
        for(unsigned int j = 0; j < m; j++) {
                double *row = values[j];
                for(unsigned int i = 0; i < n; i++) row[i] = drng();
        }
}
*/

// ####################################

QuickVector *QuickMatrix::normalizeRows() {
        QuickVector *ret = new QuickVector(m);

        for(unsigned int j = 0; j < m; j++) {
                double *row = values[j];
                unsigned int max_loc = 0;

                for(unsigned int i = 0; i < n; i++) {
                        if(fabs(row[max_loc]) < fabs(row[i])) max_loc = i;
                }

                double scalar = 1.0 / row[max_loc];

                (*ret)[j] = scalar;

                for(unsigned int i = 0; i < n; i++) row[i] *= scalar;
        }

        return ret;
}

// ####################################

QuickVector *QuickMatrix::operator *(const QuickVector *operandvec) const {
        if(operandvec->size() != n) return NULL;

        QuickVector *ret = new QuickVector(m);

        for(unsigned int i = 0; i < m; i++) {
                double sum = 0;
                for(unsigned int j = 0; j < n; j++)
                        sum += values[i][j] * (*operandvec)[j];
                (*ret)[i] = sum;
        }

        return ret;
}

// ####################################

QuickMatrix *QuickMatrix::operator +=(const QuickMatrix *operandmat) {
        if(operandmat->n != n || operandmat->m != m) return NULL;

        for(unsigned int i = 0; i < m; i++) {
                for(unsigned int j = 0; j < n; j++)
                        values[i][j] += operandmat->values[i][j];
        }

        return this;
}

// ####################################

QuickMatrix *QuickMatrix::operator *(const QuickMatrix *operandmat) const {
        if(operandmat->m != n) return NULL;

        QuickMatrix *ret = new QuickMatrix(m,operandmat->n);

        for(unsigned int i = 0; i < m; i++) {
                for(unsigned int j = 0; j < operandmat->n; j++) {
                        double sum = 0;
                        for(unsigned int k = 0; k < n; k++) 
                                sum += values[i][k] * operandmat->values[k][j];
                        ret->values[i][j] = sum;
                }
        }

        return ret;
}

// ###################################

void QuickMatrix::dumpToAux() const {
        for(unsigned int j = 0; j < m; j++) {
                for(unsigned int i = 0; i < n; i++)
                        cout << values[j][i] << ' ';
                cout << endl;
        } 
}

// ###################################

void QuickMatrix::fillWithZero() {
        for(unsigned int j = 0; j < m; j++) {
                memset(values[j], 0, n*sizeof(double)); // fastest method. =)
        }
}

// ###################################
// sets the diagonal to a constant.
QuickMatrix *QuickMatrix::operator =(const double y) {
        fillWithZero();
        unsigned int size = n;
        if(size > m) size = m;

        for(unsigned int i = 0; i < size; i++) values[i][i] = y;
        return this;
}

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Ktechlab-devel mailing list
Ktechlab-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ktechlab-devel

Reply via email to