?
Solved

I need a very simple matrix class

Posted on 2001-09-01
11
Medium Priority
?
299 Views
Last Modified: 2013-12-14
My code presently has the following ugly form:

int NUMROWS, NUMCOLS ;

float* ArrayA = new float[ NUMCOLS * NUMROWS ] ;
//
// Initialize ArrayA to 0.0
//
for ( int i = 0 ; i < NUMROWS; i++ ) {
  for (int j = 0 ; j < NUMCOLS; j++ ) {
     ArrayA[ i + j * NUMROWS ] = (float) 0.0 ;
  }
}


I hate that code for a number of reasons:  it hides the natural two-dimensional structure of the matrix by exposing the indexing arithmetic.  It also uses new/delete
and I would rather use constructor/destructor.  And,
I don't like declaring ArrayA as a pointer when it
is really a vector (or better yet a matrix).

I would much rather use:  
  float ArrayA[NUMCOLS][NUMROWS}    
  .
  .
  .
  ArrayA[i][j] = 0.0 ;

But, NUMCOLS and NUMROWS are not constants and Microsoft
Visual C++ wants them to be constants.

I just want a short (less than 50 line) class that
would allow be to avoid using new and will allow
Array[i][j] or Array(i,j) syntax on both sides of
the equal sign.  I don't want to have to include
a .h file - I just want 50 lins or less than I can
include in my file.  Better yet, I'd like to figure out how to use standard features of C++, or possibly STL.

Thanks,
  Ken




0
Comment
Question by:klopter
  • 3
  • 2
  • 2
  • +3
11 Comments
 
LVL 4

Expert Comment

by:jtwine100697
ID: 6448438
> float ArrayA[NUMCOLS][NUMROWS}    
> ArrayA[i][j] = 0.0 ;

Unless I am mistaken, you should be able to dynamically allocate this array like this:

    float  **ppMatrix = new float*[ 4 ];

    **ppMatrix[ 0 ] = new float[ 4 ];
    **ppMatrix[ 1 ] = new float[ 4 ];
    **ppMatrix[ 2 ] = new float[ 4 ];
    **ppMatrix[ 3 ] = new float[ 4 ];
    //
    // Or For A NUMCOLS x NUMROMS Matrix...
    //
    float  *ppMatrix = new float*[ NUMCOLS ]

    for( DWORD dwCol = 0; dwCol < NUMROWS; dwCol++ )
    {
        ppMatrix[ dwCol ] = new float[ NUMROWS ];
    }

The first example would yield a 4x4 matrix that you can use like this:

    ppMatrix[ 0 ][ 0 ] = 1.0;
    ppMatrix[ 0 ][ 1 ] = 1.0;
    ppMatrix[ 0 ][ 2 ] = 1.0;
    ppMatrix[ 0 ][ 3 ] = 1.0;
    ppMatrix[ 1 ][ 1 ] = 1.0;
    ppMatrix[ 1 ][ 2 ] = 1.0;
    ppMatrix[ 1 ][ 3 ] = 1.0;
    //
    // Etc...  Be Sure To Free Each "Column" When Done...
    //

Thoughts?

--------------

> I just want a short (less than 50 line) class that
would allow be to avoid using new and will allow

I do not think that you are going to get around having to use new/delete someplace, either in the class you want or outside of it.  

A web search provides several links to Matrix class-libraries, but I am not sure exactly what you are looking for in a class-library.

-=- James.
0
 
LVL 4

Expert Comment

by:jtwine100697
ID: 6448440
" float  *ppMatrix" should be " float  **ppMatrix"; sorry about that.

-=- James.
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 6448478
Usually, I use 1 dimension arrays, something like this:

#define INDEX(i,j) iIndex = i +j*NUMCOLS
double *aArray = new double[NUMCOLS*NUMROWS];
memset( aArray ,0, NUMCOLS*NUMROWS*sizeof(double));
now for get/set element you use simple formula:

aArray[INDEX(i,j)] = myValue ;

delete [] aArray ;
PS: better use double(not float) for computations
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
LVL 2

Expert Comment

by:smitty1276
ID: 6448526
There is a math library called matlib that's supposed to be pretty good, and it's supposed to be geared towards matrices and vectors.  I *THINK* its free, but I'm not sure.  You may want to look around for that.
0
 

Expert Comment

by:Riyadh_Moosa
ID: 6448841
TrY this, I've tested it on VC++ 6.0.  It allows you to have 2D Matrix of any size, but no encapsulation of the data members (that requires more complicated coding, but can be done).  Let me know what you think.


  cut-and-past the code below and compile
====================================================
#include <iostream.h>


class matrix{
public:
     matrix(int cNum, int rNum);
     ~matrix();
     

     int          NUMCOLS, NUMROWS;
     float     **element;
};


matrix::matrix(int cNum, int rNum) : NUMCOLS(cNum), NUMROWS(rNum)
{
     element = new float*[NUMCOLS];
     for(int i =0 ; i<NUMCOLS ; i++)
     {
          element[i] = new float[NUMROWS];
     }
         
}

matrix::~matrix()
{
     for(int i = 0; i< NUMCOLS; i++)
          delete [] element[i];
     delete [] element;
}


void main()
{
     int Cols, Rows;
     int i, j;

     cout << "Enter No. of matrix Columns in Matrix: ";
     cin  >> Cols;
     cout << "Enter No. of matrix Rows in Matrix: ";
     cin  >> Rows;

     matrix ArrayA(Cols, Rows);

     for (i=0 ; i<Cols; i++)
          for (j=0 ; j<Rows; j++)
               ArrayA.element[i][j] = (float) ((i*10) + (j*1));

     for ( i=0 ; i<Cols; i++)
          for ( j=0 ; j<Rows; j++)
               cout << i << ',' << j << ':'  << ArrayA.element[i][j] << endl;

}
===========================================
0
 

Expert Comment

by:Riyadh_Moosa
ID: 6448845
TrY this, I've tested it on VC++ 6.0.  It allows you to have 2D Matrix of any size, but no encapsulation of the data members (that requires more complicated coding, but can be done).  Let me know what you think.


  cut-and-past the code below and compile
====================================================
#include <iostream.h>


class matrix{
public:
     matrix(int cNum, int rNum);
     ~matrix();
     

     int          NUMCOLS, NUMROWS;
     float     **element;
};


matrix::matrix(int cNum, int rNum) : NUMCOLS(cNum), NUMROWS(rNum)
{
     element = new float*[NUMCOLS];
     for(int i =0 ; i<NUMCOLS ; i++)
     {
          element[i] = new float[NUMROWS];
     }
         
}

matrix::~matrix()
{
     for(int i = 0; i< NUMCOLS; i++)
          delete [] element[i];
     delete [] element;
}


void main()
{
     int Cols, Rows;
     int i, j;

     cout << "Enter No. of matrix Columns in Matrix: ";
     cin  >> Cols;
     cout << "Enter No. of matrix Rows in Matrix: ";
     cin  >> Rows;

     matrix ArrayA(Cols, Rows);

     for (i=0 ; i<Cols; i++)
          for (j=0 ; j<Rows; j++)
               ArrayA.element[i][j] = (float) ((i*10) + (j*1));

     for ( i=0 ; i<Cols; i++)
          for ( j=0 ; j<Rows; j++)
               cout << i << ',' << j << ':'  << ArrayA.element[i][j] << endl;

}
===========================================
0
 

Expert Comment

by:Riyadh_Moosa
ID: 6448865
Sorry for the repeat, I had a problem w/ the browser.

Some explaination on the above:
The constructor in the code above allows you to dynamically allocate memory to a 2D array: it first allocates memory to a 1D array of POINTERS to float, then goes to each element of this pointer array and makes it a 1D array of floats (just like in your code).

The matrix data can be accessed as normal through the member "element" (i.e. element[x][y]) as illustrated in the test in main().

Hope this helps.
0
 
LVL 4

Accepted Solution

by:
IainHere earned 600 total points
ID: 6450195
#include <vector>

template<class T_> class Array2D
{
public:
     Array2D(int sizeX, int sizeY);
     int                    GetX() const;    
     int                    GetY() const;
     virtual               ~Array2D() {};
     T_&                    operator() (int X, int Y);
     T_                    operator() (int X, int Y) const;

protected:
     int                    m_x;
     int                    m_y;
     std::vector<T_>     m_data;
};

template<class T_>
inline T_& Array2D<T_>::operator() (int X, int Y)
{
     ASSERT((m_x*Y + X) < (m_x * m_y));
     return m_data[m_x*Y + X];
}

template<class T_>
inline T_ Array2D<T_>::operator() (int X, int Y) const
{
     ASSERT((m_x*Y + X) < (m_x * m_y));
     return m_data[m_x*Y + X];
}

template<class T_>
Array2D<T_>::Array2D(int sizeX, int sizeY) :     m_x (sizeX),
                                                            m_y (sizeY),
                                                            m_data (std::vector<T_>(m_x*m_y, 0))
{    
}

template<class T_>
int Array2D<T_>::GetX() const
{
     return m_x;
}

template<class T_>
int Array2D<T_>::GetY() const
{
     return m_y;
}

typedef Array2D<float> matrix;

This method has some advantages over those above (data encapsulation, the ability to use it for other data types, slightly stronger resistence to errors, I like the syntax more, but that's a personal thing).  I use a version of this with more error checking (out of bounds throwing an exception etc.) - if you're interested, ask.  Obviously, it wouldn't be much work to make it into a concrete class.  The same example as above, but using the different version of matrix (apologies to Riyadh_Moosa, but I thought it would be clearer if our classes both used the same demo code :-)

void main()
{
    int Cols, Rows;
    int i, j;

    cout << "Enter No. of matrix Columns in Matrix: ";
    cin  >> Cols;
    cout << "Enter No. of matrix Rows in Matrix: ";
    cin  >> Rows;

    matrix ArrayA(Cols, Rows);

    for (i=0 ; i<Cols; i++)
         for (j=0 ; j<Rows; j++)
              ArrayA(i,j) = (float) ((i*10) + (j*1));

    for ( i=0 ; i<Cols; i++)
         for ( j=0 ; j<Rows; j++)
              cout << i << ',' << j << ':'  << ArrayA(i,j) << endl;

}
0
 
LVL 4

Expert Comment

by:IainHere
ID: 6450220
>> m_data (std::vector<T_>(m_x*m_y, 0))

By the way, this initializes the vector to 0, and can only be used on objects that can be initialized like this:

float bob(0);

If you wanted to use it on data types without this constructor, you would have to make the line read std::vector<T_>(m_x*m_y)), and initialize the elements yourself.  It'll work fine as it is for float, though.
0
 

Author Comment

by:klopter
ID: 6450918
This is exactly what I was looking for.  

One thing that I failed to mention, but which these code handles perfectly, is that I need the resulting data to be stored consequetively in  memory because I will pass it to a C routine that expects the data that way.  

Thanks,
  Ken
P.S.  To others:  Thanks for your comments.  
0
 

Author Comment

by:klopter
ID: 6451072
Just one last thing:  
  To pass the address of ArrayA(0,0) to an extern "C" routine which is expecting an array of floats, I pass
it:  &ArrayA(0,0).

  Is there any way to get ArrayA to convert to &ArrayA(0,0) automatically in this situation?

Thanks,
  Ken
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand column That will then direct you to their download page. From that p…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

589 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question