Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

I need a very simple matrix class

Posted on 2001-09-01
11
Medium Priority
?
284 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

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…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

670 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