Sign in to follow this  

Overload comma , operator to init the array

This topic is 1960 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

Hello,

I would like to overload comma , operator so it would be able to init the array.
The array is in the class:
[code]
template <class DataType,class IntType>
class Matrix
{
public:
DataType *Elements;
IntType Rows, Cols;
//some other functions and operators
};
[/code]

How do I achieve the functionality lik in the blitz++ library, that allows to use such syntax:
[code]
Matrix<float,int> M;
M.Resize(2,2);
M=1, 0,
0, 1;
[/code]

I have read some tutorials on internet and posts on gamedev and stackoverflow but I havent found what I was really looking for. Also tried to find implementation in blitz++ of this feature but without success.

Any help or suggestions would be appreciated,
Thanks in advance Edited by Misery

Share this post


Link to post
Share on other sites
Who cares if he overloads the , operator anyway? Its not like he is going to be doing anything useful for the next few years, given his choice of language.

As an empiricist, I say let him do it and learn the consequences for himself.

Share this post


Link to post
Share on other sites
Actually the initializer list solves the whole problem very well. But just one more question.
How do I make a constructor that could build the matrix using syntax like that (assuming that one can write here any number of rows):
[code]
M={
{1,2,3} //row 1
{4,5,6} //row 2
{7,8,9} //row 3
};
[/code]
That is a problem because matrix defined in such manner can have any number of arguments (rows). How do I make that working? Should I use a variadic template?

Share this post


Link to post
Share on other sites
[quote name='Misery' timestamp='1343422146' post='4963751']
Actually the initializer list solves the whole problem very well. But just one more question.
How do I make a constructor that could build the matrix using syntax like that (assuming that one can write here any number of rows):
[code]
M={
{1,2,3} //row 1
{4,5,6} //row 2
{7,8,9} //row 3
};
[/code]
That is a problem because matrix defined in such manner can have any number of arguments (rows). How do I make that working? Should I use a variadic template?
[/quote]

Unfortunately, this is not as clean:
[url="https://groups.google.com/group/comp.lang.c++/browse_thread/thread/eaf9a9f758529624/51d7802958427622"]https://groups.googl...1d7802958427622[/url]

However, you may consider supplying the arguments similarly to what you had in mind in your [font=courier new,courier,monospace]operator,[/font] solution:
M={
1,2,3, //row 1
4,5,6, //row 2
7,8,9 //row 3
}; Edited by Matt-D

Share this post


Link to post
Share on other sites
@Matt-D: That of course is a solution (and a good one really). But absolutely beautiful it would be if I could use the syntax with lists in the list.
Actually I have created a template variadic constructor, and it works. However there is only one more thing: how can I find out the number of arguments (rows) given so I could allocate the *Data?
[code]
template <class ... Args>
Matrix(Args ... args)
{
//do stuff
}
[/code]

When I use a code like the one given with "rows", it calls this constructor. If I could somehow estimate the number of rows, I wouldn't need to call Alloc before using the lists.

Share this post


Link to post
Share on other sites
You could also create a temporary and hidden struct just for initialization, if you really want that syntax.

Something like this:
[code]
template <typename Type>
class MyMatrixRow
{
public:
MyMatrixRow(Type column1, Type column2, Type column3) :
column1(column1), column2(column2), column3(column3) { }

Type column1, column2, column3;
};

template <typename Type>
class MyMatrix
{
public:
MyMatrixRow(MyMatrixRow<Type> row1, MyMatrixRow<Type> row2, MyMatrixRow<Type> row3)
{
data.resize(9);

data[0] = row1.column1;
data[1] = row1.column2;
data[2] = row1.column3;

data[3] = row2.column1;
data[4] = row2.column2;
data[5] = row2.column3;

data[6] = row3.column1;
data[7] = row3.column2;
data[8] = row3.column3;
}

private:
std::vector<Type> data;
};[/code]

The structs passed in to the constructor are just used for constructing and then discarded.

The code:
[code]MyMatrix<float> matrix = {{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f}};[/code]

Actually turns into:
[code]MyMatrix<float> matrix(MyMatrixRow<float>(0.0f, 0.0f, 0.0f),
MyMatrixRow<float>(0.0f, 0.0f, 0.0f),
MyMatrixRow<float>(0.0f, 0.0f, 0.0f));[/code]

...and hopefully the entire MyMatrixRow() thing would be compiled out, but I don't know anything about compiler optimizing so I can't say for sure. Edited by Servant of the Lord

Share this post


Link to post
Share on other sites
OMG why doesn't initializer_list constructors work in VS2010?? [img]http://public.gamedev.net//public/style_emoticons/default/sad.png[/img]
On Linux GCC it works just fine :|

EDIT: it doesn't support this functionality so I have to cancel it at the moment, as my project has to be portable. Pity.

Anyway thanks for help very much. Edited by Misery

Share this post


Link to post
Share on other sites
Thanks to ([b]Servant of the Lord[/b])'s idea I've managed to do a syntax that works exactly as I wanted, and - at least to me (but I'm not an experienced programmer) - seems quite effective. To get even nicer, this solution cannot be used in VC++ but, it doesn't collide with it (maybe someday they will support init lists, as they have appropriate headers and stuff). So this initializer constructor can be defined, but cannot be used in VC++, but works with compiers that support this feature. I have tested it in Ubuntu Linux 12.04 with its default GCC compiler suite. I'm just putting it here if someone would search for such snippet.

Thanks Gyus for Your time! And special thanks for suggestions not to overload comma operator. :]

The row class:
[code]
template<class DATA_TYPE,class INT_TYPE>
class Row
{
public:
Row()
{ }
Row(const initializer_list<DATA_TYPE> &list) : L(list)
{ }
DATA_TYPE operator [](INT_TYPE i) const
{
return *(L.begin()+i);
}
INT_TYPE Size() const
{
return L.size();
}
private:
const initializer_list<DATA_TYPE> &L;
};
[/code]

Matrix class:
[code]
template<class DATA_TYPE,class INT_TYPE>
class Matrix
{
public:
DATA_TYPE *Data;
INT_TYPE Rows,Cols;
Matrix()
{
cout<<"basic ctr"<<endl;
Data=NULL;
Rows=0;
Cols=0;
}
Matrix(initializer_list<DATA_TYPE> RowVec) //initializer for M={1,2,3,...,N}
{
Data=NULL;
Rows=0;
Cols=0;
Cols=RowVec.size();
if (Cols==0) Free();
else
{
Alloc(1,Cols);
INT_TYPE k=0;
typename initializer_list<DATA_TYPE >::iterator i=RowVec.begin();
for (i=RowVec.begin();i!=RowVec.end();i++) Data[k++]=*i;
}
}
Matrix(initializer_list<Row<DATA_TYPE,INT_TYPE> > RowsL) //initializer for M= { {}, {}, {}}
{
Data=NULL;
Rows=0;
Cols=0;
Rows=RowsL.size();
if (Rows==0) Free();
else
{
INT_TYPE k=0;
typename initializer_list<Row<DATA_TYPE,INT_TYPE> >::iterator i=RowsL.begin();
Cols=(*i).Size();
Alloc(Rows,Cols);
for (i=RowsL.begin();i!=RowsL.end();i++)
{
if (Cols!=(*i).Size()) { Free(); /* throw an error: inconsistient row/colums dimensions*/cout<<"Err: ircd"<<Cols<<endl;}
else
{
for (int j=0;j<(*i).Size();j++)
{
Data[j*Rows+k]=(*i)[j];
}
}
k++;
}
}
}
void Alloc(INT_TYPE R,INT_TYPE C)
{
Free();
Data=new DATA_TYPE[R*C];
Rows=R;
Cols=C;
}
void Free()
{
delete[] Data;
Data=NULL;
Rows=0;
Cols=0;
}
};
[/code]

And now it is possible to use initialzier lists, in similar way as it is in Mathematica. So it is possible to init any rectangular array in a nice looking and intuitive fashion, for example:
[code]
Matrix<float,int> M,E,r,c;
M={
{0,1,0},
{0,0,0},
};

E={
{1,0,0},
{0,1,0},
{0,0,1}
};

r={3,2,1};
c={
{1},
{2},
{3},
{4}
}
[/code]

Regards [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

PS.: #include <initializer_list> Edited by Misery

Share this post


Link to post
Share on other sites
Seriously now, why are you needing to frequently initialise matrices with lists of constants?

Would it not be clearer to have stuff like:

[code]
Matrix identityMatrix();
Matrix rotationZMatrix(float angle);
[/code]

and just do whatever is easiest to implement inside these relatively few functions?

Be far more clear reading code that uses named methods to construct matrices than wading through code containing any of the above, no matter how the detail of the initialisation syntax happens to be expressed.

Share this post


Link to post
Share on other sites
@[b]Aardvajik[/b]:
Hello,
I am a scientist in CFD. I was asked to create a "friendly" library for scientific computations. I know, there are many of those, but none of them fulfills all of these criteria at once:
- includes matrix classes, sparse matrix classes, graphs, FEM meshes, solvers (I know, I know, Dune does for example) under one common interface
- is intuitive for people using Scilab, Matlab, Octave, Mathematica etc (this is why I aim to create such syntax)
- has easy to use installer on both Windows and Linux
- is portable between Windows/Linux and Intel C++, VS C++ and GCC on those platforms
- is written in compiled language, so it is much faster than scientific script languages, and avoids copying of arrays (what is common in Scilab for example)
- to use: include only one header and done, no needed fortran to C and C to C++ etc compilations, using Linux to windows cross compilers and so on

And to give You straight answer: Engineers and scientists very often use Mathematica, Matlab and silimar things.
And quite often we begin to learn programming using these (btw great) packages. And these script languages are oriented for using matrices, the same way as it is in engineering practice. We are used to init matrices "by hand". However, as one develops oneself tries to count more and more complicated things. And at some moment those scientific packages seem too slow, even to use them at super computers (on our HPC Task server, if Your computations are not finished in a week, they are canceled).

So what I am trying to do is to create intuitive library, which can be easily installed and used by non-proffesional programmers (like myself).So they could easily count much larger cases than before.

I am guessing that You are a pro programmer. So Your viewpoint to this matter is quite different than someones who is just trying to do different job, but needs to create program to count anything. For You it is not a problem to choose a language, dependently to what You need to achieve. You need a good parsing - take Python, You need fast numerical algorithms - take C++ or Fortran. Need administrative scripts: take PowerShell or Perl...
But we - non-profesionals - don't look at those matters this way. Our job demands from us bit different things, and we are not (unfortunately) paid for spending time on learing new programming language.

You would be surprised how little most just-programming-users enigneers know about programming. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] Edited by Misery

Share this post


Link to post
Share on other sites
[quote name='Misery' timestamp='1343466064' post='4963893']
@[b]Aardvajik[/b]:
Hello,
I am a scientist in CFD. I was asked to create a "friendly" library for scientific computations. I know, there are many of those, but none of them fulfills all of these criteria at once:
- includes matrix classes, sparse matrix classes, graphs, FEM meshes, solvers (I know, I know, Dune does for example) under one common interface
- is intuitive for people using Scilab, Matlab, Octave, Mathematica etc (this is why I aim to create such syntax)
- has easy to use installer on both Windows and Linux
- is portable between Windows/Linux and Intel C++, VS C++ and GCC on those platforms
- is written in compiled language, so it is much faster than scientific script languages, and avoids copying of arrays (what is common in Scilab for example)
- to use: include only one header and done, no needed fortran to C and C to C++ etc compilations, using Linux to windows cross compilers and so on
[/quote]

Hey, have you considered looking into Eigen, http://eigen.tuxfamily.org/dox-devel/ ?
I think that it fulfills most of your requirements, other than some of the first one and the last one (I think, I usually just include what I need, but this one is trivial to solve if you prepare a header that would include everything -- not that I think it's a good practice, btw) -- but relatively speaking, since writing from the scratch seems to be your alternative anyway, wouldn't it be faster to build on Eigen as a foundation (and if you contribute your addons to an open-source project you'll get other benefits, like more eyes to catch more bugs, etc.),

Share this post


Link to post
Share on other sites
@[b]Matt-D[/b]:
Thank You for this suggestion. The lib seems quite interesting. I'm sure I will take a look at sources of Eigen, especially iterative solvers - that's what I was missing. But still this is matrix only package (and few more classes: plynomial for example) and I need to have a basic engineering lib that contains a bit more.
Maybe I should add a few more words of explanation:

I decided to create my own library that will be similar in usage to Scilab and/or Mathematica. So in general it will be some kind of code-compiled matrix operator. I am not trying to do everything from scratch, because probably my life wouldn't be long enough to make a good quality lib (creating a good sparse solver or mesh generator are another branches of sciences themselves). I am trying to make a reasonably fast and convenient common, homogenous interface to few well known and portable libraries. And this interface is my main job at the moment.
I will integrate (or already have integrated some of those libs/programs):
-CBLAS and CLAPCK,
-CGAL, GMSH, provide GiD mesh generator interface,
-Umfpack, SuperLU for sparse matrices.
-Intel MKL and AMD MKL support
And some more... maybe Boost.units? Time will show. For now I needed a realistic goal to achieve. In future I plan to integrate VTK and make python bindings.
I will add many of functions written by myself "copying" the functionality known from Scilab and Mathematica. Interpolation, differentation, integration and so on...
And if this lib become successful among my friends at work, and my students I will be happy to make it open-source (in the meaning that it will be well documented for developers and users, and tested and ready to download), as most of those libs are GPL licensed.

And why I will not use Eigen as a foundation? First if all: it is too late now to change the abosule basis. Second I want to have as much control over this project as possible. Third: I love programming and it gives me much fun.

Regards

Share this post


Link to post
Share on other sites
[quote name='Misery' timestamp='1343466064' post='4963893'] Engineers and scientists very often use Mathematica, Matlab and silimar things.
And quite often we begin to learn programming using these (btw great) packages. And these script languages are oriented for using matrices, the same way as it is in engineering practice. We are used to init matrices "by hand". However, as one develops oneself tries to count more and more complicated things. And at some moment those scientific packages seem too slow, even to use them at super computers (on our HPC Task server, if Your computations are not finished in a week, they are canceled).
[/quote]

But at this point -- when something like MatLab becomes too slow -- I think a better approach than switching to an entirely new language with an entirely new library, etc., is to stick with the original engineering environment but write extensions to it in C++ using the API exposed by its developer. In the case of MatLab MathWorks gives you the whole MEX interface and, I think, even has a MEX Compiler built into Matlab, so what you can do is profile your Matlab computations and re-write the slow parts in C++ interfacing via MEX. Anyway, that's what we did at my last job and it worked pretty well.

Not sure if Mathematica has something like this, but I'd actually be pretty surprised if it didn't Edited by jwezorek

Share this post


Link to post
Share on other sites
@[b]jwezorek[/b]:
That's true, but when taking into concern Matlab or Mathematica the cost of those is very high. Especially Mathworks strategy is painful: You have to pay about $470 for each component. For deployment tool, for compiler... Why not use free tools? Or just make a GPL code that will work on most compilers.
And still those Mathematica and Matlab libraries are distributed as dll's (or so). How would anybody move such application to different platform. Let's say to platform with Itanium processors?

Matlab and Mathematica are really great tools, but it is for a reason why I decided tf rsuch solution.
[img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

Share this post


Link to post
Share on other sites

This topic is 1960 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this