Jump to content
  • Advertisement
Sign in to follow this  
Sync Views

Matrix design problem

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 view
void Transpose();
void Transpose(const Matrix &From);

// this is far less confusing - the verb here is Get rather than Transpose
Matrix GetTranspose() const;

HTH

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 0
Matrix::Matrix( unsigned int width, unsigned int height )
: h(height),
w(width)
{
for( int i = 0; i < h*w; ++i )
matrix.push_back( 0 );
}



/// Matrix operation
bool 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 dimensions
int Matrix::width() const
{
return w;
}

int Matrix::height() const
{
return h;
}



/// Matrix transformations
void 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 this post


Link to post
Share on other sites
Quote:
Original post by Sync Views
If 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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!