Public Group

# Matrix design problem

This topic is 3662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I want to have a varity of sizes from say 2X2 to mayby 5X5. I considerd writing a generic class but which ever way I look at it there seems to be quite a heavy overhead checking both are the same size in operators and storing a dynamic amount of memory... For this reason I'm considering just making a bunch of glasses instead of one eg "Matrix3X3","Matric4X4" etc, but this means alot of duplicate code and if I change one I'll need to change like 6 others :( Is there a good solution for having just one bunch of code for all the sizes without a heavy overhead? EDIT: Also what should I do in cases like these as I can't ovload all 3 cases :( Transpose function: 1- Apply it on this class "void Transpose()" 2- Return a new matrix "Matrix Transpose()const" 3- "void Transpose(const Matrix &From)" [Edited by - Sync Views on June 14, 2008 4:43:06 AM]

##### Share on other sites
Templates?

template<int x,int y> class matrix{private:    int v[x*y];public:    matrix(){ }    int &operator()(int c,int r){ return v[(r*x)+c]; }};int main(){    matrix<3,3> m;    matrix<8,8> n;    m(1,2)=23;}

Of course, the data type of the matrix could easily be a parameter of the template as well.

This way, the bounds are resolved at compile time, so there is no runtime overhead compared to using explicit bounds, and for what it is worth, your matrix data is on the stack when the matrix is a local.

Downside is that each differently sized matrix is a distinct type, so you can't treat all matrices as the same.

Regarding your overloads, if there is any confusion with overload names, just be more explicit in your naming. It will make your code clearer in the long run:

// these are pretty clear candidates for overload in my viewvoid Transpose();void Transpose(const Matrix &From);// this is far less confusing - the verb here is Get rather than TransposeMatrix GetTranspose() const;

HTH

##### Share on other sites
If you're using C++, you can use templates to specify dimensions, and write your operators in those terms as well. You'll also get the benefit of having everything be type safe, and have the dimension checking done at compile time. You can get the templates to do everything for you, from sizing the matrices up correctly [and at compile time no less], to forcing all the loops to be completely unrolled, to making sure everything gets inlined within your ops.

In C++ its easy. Other languages, you aren't so lucky.

Its a bit of a toss up, but you might be able to get the compiler to help you out a bit in languages like java and C# if you can express your matrices in terms of constant [have the dimensions passed in the constructor, and have the constructors actually fed by inheriting classes that produce compile-time-known constants]. It really depends, but some JIT's will nab this sort of thing, and replicate the constructor with the various constants, and unroll all the loops and such for the operations. It really depends heavily on the optimizations that the JIT performs, but I know that this sort of thing can be done in a JIT. Also know that there exist java implementations that do it. I don't know about C# [as I haven't seen many open source JITs for C#].

Even then though, you would be depending on something that may or may not be there.

In all honesty, I used a generative programming approach for my C# and Java math library. I don't trust the compiler unless I know it'll do what I want it to.

##### Share on other sites
If I use templates what of the matrix functions which can operate on matrices of diffrent sizes (eg matrix multiplication)?

Also anthoer concept I came up with but not aure if it's such a great idea.

What if I wrote a program that takes my own template type thing and generates a source file for matrix classes from say 1x2 to 5x5 complete with all the functions that can accept diffrent size matrices?

##### Share on other sites
No need for that, you can just use some sort of dynamic container (like std:vector). I wrote a Matrix class a few days ago, you can take a look at it if you want. It's not perfect, but it does the job (I use it to store various elements for Tetris)

////// matrix.h//////#ifndef MATRIX_H#define MATRIX_H#include "matrix.h"#include <vector>/// ////// ////// Matrix ////// ////// ///class Matrix{public:    //Matrix();    Matrix( unsigned int width = 0, unsigned int height = 0 );    //~Matrix();    // Returns true on success    bool set( unsigned int x, unsigned int y, unsigned int i );    // Get value, -1 on failure    int get( unsigned int x, unsigned int y ) const;    // Get dimensions    int width()  const;    int height() const;    // Transformations    void flipcw();    void flipccw();private:    std::vector<unsigned int> matrix;    unsigned int w, h;};#endif // TETRIS_H

////// matrix.cpp//////#include "matrix.h"/// ////// ////// Matrix ////// ////// ///// Constructor creates matrix full of 0Matrix::Matrix( unsigned int width, unsigned int height ): h(height),  w(width){    for( int i = 0; i < h*w; ++i )      matrix.push_back( 0 );}/// Matrix operationbool Matrix::set( unsigned int x, unsigned int y, unsigned int i ){    if( x < w && y < h ) {        matrix[x+w*y] = i;        return true;    }    return false;}int Matrix::get( unsigned int x, unsigned int y ) const{    if( x < w && y < h )      return matrix[x+w*y];    return -1;}/// Matrix dimensionsint Matrix::width() const{    return w;}int Matrix::height() const{    return h;}/// Matrix transformationsvoid Matrix::flipcw(){    // Only flip if the matrix is square    if( w == h ) {        // Make a quick copy of the current matrix        Matrix tmp( *this );        // Transform!        for( int x = 0; x < w; ++x ) {            for( int y = 0; y < h; ++y ) {                this->set( x, y, tmp.get( y, h-x-1 ) );            }        }    }}void Matrix::flipccw(){    // Only flip if the matrix is square    if( w == h ) {        // Make a quick copy of the current matrix        Matrix tmp( *this );        // Transform!        for( int x = 0; x < w; ++x ) {            for( int y = 0; y < h; ++y ) {                this->set( x, y, tmp.get( w-y-1, x ) );            }        }    }}/// End of matrix.cpp///

edit:
I don't know why, but whenever I post source code copied from a source file on Linux in [source] tags, it screws with the newlines. Just ignore the extra newlines please.

##### Share on other sites
Quote:
 Original post by Sync ViewsIf I use templates what of the matrix functions which can operate on matrices of diffrent sizes (eg matrix multiplication)?

There's three things you can do:

A) Write a simple generic algorithm that multiplies any two compatible matrices - using for loops.
B) Specialise certain cases, presumably to optimise away the for loops, i.e. (2x2)(2x2), etc.
C) Use template meta-programming to similarly optimise for all compatible matrices by avoiding for loops for 'small' matrices and using loops for 'large' matrices.

Quote:
 Also anthoer concept I came up with but not aure if it's such a great idea.What if I wrote a program that takes my own template type thing and generates a source file for matrix classes from say 1x2 to 5x5 complete with all the functions that can accept diffrent size matrices?

That's another form of metaprogramming, templates can do this for you in a more flexible manner, so I don't see the need.

As for transposition and like functions: If your matrix class has element accessors then transpose should be a non-member function.

I'd be tempted to adopt this function, it transposes the argument and then returns it:

Matrix & transpose(Matrix & m);

and similarly:

Matrix & invert(Matrix & m);

Use:

m2 = invert( transpose(m1) );
// m1 == m2 == true

1. 1
2. 2
3. 3
Rutin
19
4. 4
5. 5

• 14
• 12
• 9
• 12
• 37
• ### Forum Statistics

• Total Topics
631424
• Total Posts
3000008
×