Solved

I need a very simple matrix class

Posted on 2001-09-01
11
257 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
 
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
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

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 150 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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
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…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

744 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now