Solved

I need a very simple matrix class

Posted on 2001-09-01
11
263 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
NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

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

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
C++ question 3 65
C++ :Change value from  DisableCMD registry 4 60
draw a Christmas tree by using a nested loop? 26 62
No module found pypyodbc, 3 18
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

803 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