I am trying to create a multi-dimensional histogram using multi-dimentional vectors and I don't know the dimension size ahead of time. Any ideas on how to do this in c++?
Mustafa
Write your own class. For starters, you'll probably want
something along the lines of:
class MultiDimVector
{
std::vector<int> myDims;
std::vector<double> myData;
public:
MultiDimVector( std::vector<int> dims )
: myDims( dims )
, myData( std::accumulate(
dims.begin(), dims.end(), 1.0, std::multiplies<int>() )
{
}
};
For indexing, you'll have to take an std::vector<int> as the
index, and calculate it yourself. Basically something along the
lines of:
int MultiDimVector::calculateIndex(
std::vector<int> const& indexes ) const
{
int results = 0;
assert( indexes.size() == myDims.size() );
for ( int i = 0; i != indexes.size(); ++ i ) {
assert( indexes[i] < myDims[i] );
results = myDims[i] * results + indexes[i];
}
return results;
}
You can use std::vector, like:
std::vector<std::vector<yourType> >
(or maybe if you use a framework you can search it's documentation for a better integrated array replacement ;) )
vector<vector<int>> mutli_dim_vector_name(num_rows, (vector<int>(num_cols, default_value)));
// You can use this format to further nest to the dimensions you want.
Related
I am creating a sparse matrix in CSR format, for which I start with a vector of matrix element structures. It needs to be std::vector at the beginning because I don't know ahead of time how many non-zeros my matrix is going to have. Then, to fill up the appropriate arrays for the CSR matrix, I need to first sort this array of non-zeros, in the order they appear in the matrix if one goes through it line-by-line. But above a certain matrix size (roughly 1 500 000 non-zeros), the sorted vector does not start from the beginning of the matrix. It is still sorted, but starts around row 44000.
// Matrix element struct:
struct mel
{
int Ncols;
int row,col;
MKL_Complex16 val;
void print();
};
// Custom function for sorting:
struct less_than_MElem
{
inline bool operator() (const mel& ME1, const mel& ME2)
{
return ( ( ME1.row*ME1.Ncols+ME1.col ) < ( ME2.row*ME2.Ncols+ME2.col ) );
}
};
int main()
{
std::vector<mel> mevec;
/* long piece of code that fills up mevec */
std::sort( mevec.begin(), mevec.end(), less_than_MElem() );
return 0;
}
I thought maybe as the vector was grown dynamically it wound up in separate blocks in the memory and the iterator wasn't pointing at the genuine beginning/end anymore. So I have tried creating a new vector and started with resizing it to the size that is known by that time. Then copied the elements one-by-one into this new vector and sorted it, but the result was the same.
Nelements = mevec.size();
std::vector<mel> nzeros;
nzeros.resize(Nelements);
for( int i = 0; i < Nelements; i++ )
{
nzeros[i].Ncols = mevec[i].Ncols;
nzeros[i].row = mevec[i].row;
nzeros[i].col = mevec[i].col;
nzeros[i].val = mevec[i].val;
}
std::sort( nzeros.begin(), nzeros.end(), less_than_MElem() );
Can anyone think of a solution?
I'm using the HoughLinesto detect line in a frame, the lines information are saved in a cv::vector<cv::Vec2f> which I handle as two dimensional array, I'm interested in the second one , it the angle of the line, I want to keep only the lines that have a angle difference greater than 1.5 rad for that here I what I did :
.............................
cv::vector<cv::Vec2f> lineQ;
..............................
// ordring the vector based on the angle value in rad
for ( int i = 0 ; i< lineQ.size()-1; i++){
for(int j= i+1;j<lineQ.size();j++){
if(lineQ[i][1] > lineQ[j][1]){
tmp = lineQ[i];
lineQ[i] = lineQ[j];
lineQ[j] = tmp;
}
}
}
now I want to compare the vector elements between each other based on the angle
cv::vector<cv::Vec2f> line;
for ( int i = 0 ; i< lineQ.size()-1; i++){
for ( int j= i+1; j<lineQ.size(); j++){
if(fabs(lineQ[i][1] - lineQ[j][1])>1.5){
line.push_back(lineQ[i]);
}
}
}
this works for 2 lines but when I got 3 whit let's say 1.3rad as an angle the size of line
is than 2. I though to use erase but this change the size of my vector !
One option is to supply a soft "equals" to std::unique_copy:
std::unique_copy(lineQ.begin(), lineQ.end(), std::back_inserter(line),
[](const cv::Vec2f & a, const cv::Vec2f & b) {
return b[1] - a[1] <= 1.5;
});
Sidenote: You can also avoid the effort of writing your own sort (Bubble sort is just about the worst choice.) and use the standard library. Something like this ought to work:
std::sort(lineQ.begin(), lineQ.end(),
[](const cv::Vec2f & a, const cv::Vec2f & b) {
return a[1] < b[1];
})).
(The above code assumes C++11, which most of us have by now. If you're stuck on an earlier version, you can write a couple of functor classes instead.)
What is the correct way to implement an efficient 2d vector? I need to store a set of Item objects in a 2d collection, that is fast to iterate (most important) and also fast to find elements.
I have a 2d vector of pointers declared as follows:
std::vector<std::vector<Item*>> * items;
In the constructor, I instantiate it as follows:
items = new std::vector<std::vector<Item*>>();
items->resize(10, std::vector<Item*>(10, new Item()));
I how do I (correctly) implement methods for accessing items? Eg:
items[3][4] = new Item();
AddItem(Item *& item, int x, int y)
{
items[x][y] = item;
}
My reasoning for using pointers is for better performance, so that I can pass things around by reference.
If there is a better way to go about this, please explain, however I would still be interested in how to correctly use the vector.
Edit: For clarification, this is part of a class that is for inventory management in a simple game. The set 10x10 vector represents the inventory grid which is a set size. The Item class contains the item type, a pointer to an image in the resource manager, stack size etc.
My pointer usage was in an attempt to improve performance, since this class is iterated and used to render the whole inventory every frame, using the image pointer.
It seems that you know the size of the matrix beforehand, and that this matrix is squared. Though vector<> is fine, you can also use native vectors in that case.
Item **m = new Item*[ n * n ];
If you want to access position r,c, then you only have to multiply r by n, and then add c:
pos = ( r * n ) + c;
So, if you want to access position 1, 2, and n = 5, then:
pos = ( 1 * 5 ) + 2;
Item * it = m[ pos ];
Also, instead of using plain pointers, you can use smart pointers, such as auto_ptr (obsolete) and unique_ptr, which are more or less similar: once they are destroyed, they destroy the object they are pointing to.
auto_ptr<Item> m = new auto_ptr<Item>[ n * n ];
The only drawback is that now you need to call get() in order to obtain the pointer.
pos = ( 1 * 5 ) + 2;
Item * it = m[ pos ].get();
Here you have a class that summarizes all of this:
class ItemsSquaredMatrix {
public:
ItemsSquaredMatrix(unsigned int i): size( i )
{ m = new std::auto_ptr<Item>[ size * size ]; }
~ItemsSquaredMatrix()
{ delete[] m; }
Item * get(unsigned int row, unsigned int col)
{ return m[ translate( row, col ) ].get(); }
const Item * get(unsigned int row, unsigned int col) const
{ return m[ translate( row, col ) ].get(); }
void set(unsigned int row, unsigned int col, Item * it)
{ m[ translate( row, col ) ].reset( it ); }
unsigned int translate(unsigned int row, unsigned int col) const
{ return ( ( row * size ) + col ); }
private:
unsigned int size;
std::auto_ptr<Item> * m;
};
Now you only have to create the class Item. But if you created a specific class, then you'd have to duplicate ItemsSquaredMatrix for each new piece of data. In C++ there is a specific solution for this, involving the transformation of the class above in a template (hint: vector<> is a template). Since you are a beginner, it will be simpler to have Item as an abstract class:
class Item {
public:
// more things...
virtual std::string toString() const = 0;
};
And derive all the data classes you will create from them. Remember to do a cast, though...
As you can see, there are a lot of open questions, and more questions will raise as you keep unveliling things. Enjoy!
Hope this helps.
For numerical work, you want to store your data as locally as possible in memory. For example, if you were making an n by m matrix, you might be tempted to define it as
vector<vector<double>> mat(n, vector<double>(m));
There are severe disadvantages to this approach. Firstly, it will not work with any proper matrix libraries, such as BLAS and LAPACK, which expect the data to be contiguous in memory. Secondly, even if it did, it would lead to lots of random access and pointer indirection in memory, which would kill the performance of your matrix operations. Instead, you need a contiguous block of memory n*m items in size.
vector<double> mat(n*m);
But you wouldn't really want to use a vector for this, as you would then need to translate from 1d to 2d indices manually. There are some libraries that do this for you in C++. One of them is Blitz++, but that seems to not be much developed now. Other alternatives are Armadillo and Eigen. See this previous answer for more details.
Using Eigen, for example, the matrix declaration would look like this:
MatrixXd mat(n,m);
and you would be able to access elements as mat[i][j], and multiply matrices as mat1*mat2, and so on.
The first question is why the pointers. There's almost never any reason
to have a pointer to an std::vector, and it's not that often that
you'd have a vector of pointers. You're definition should probably be:
std::vector<std::vector<Item> > items;
, or at the very least (supposing that e.g. Item is the base of a
polymorphic hierarchy):
std::vector<std::vector<Item*> > items;
As for your problem, the best solution is to wrap your data in some sort
of a Vector2D class, which contains an std::vector<Item> as member,
and does the index calculations to access the desired element:
class Vector2D
{
int my_rows;
int my_columns;
std::vector<Item> my_data;
public:
Vector2D( int rows, int columns )
: my_rows( rows )
, my_columns( columns )
{
}
Item& get( int row, int column )
{
assert( row >= 0 && row < my_rows
&& column >= 0 && column < my_columns );
return my_data[row * my_columns + column];
}
class RowProxy
{
Vector2D* my_owner;
int my_row;
public;
RowProxy(Vector2D& owner, int row)
: my_owner( &owner )
, my_row( row )
{
}
Item& operator[]( int column ) const
{
return my_owner->get( my_row, column );
}
};
RowProxy operator[]( int row )
{
return RowProxy( this, row );
}
// OR...
Item& operator()( int row, int column )
{
return get( row, column );
}
};
If you forgo bounds checking (but I wouldn't recommend it), the
RowProxy can be a simple Item*.
And of course, you should duplicate the above for const.
Unfortunately my math abilities and objective-c/c/c++ isn't developed enough to understand how to do this.
I have a vector set up like this:
[2,2,3,3,4,4,5,5,6,6] <-- i think thats how vectors are set up correct?
This is sort of what i think it should be set up:
vector<CGPoint>::iterator i;
vector<CGPoint>* dp = xGraph.GraphPoints;
for(i = dp->begin(); i != dp->end(); ++i){
/* grab y points only code here*/
}
Now I want to write some kind of for statement that takes xGraph.GraphPoints and only grabs the y coords.
and... i guess puts it into another vector of only y coords, which looks like [2,3,4,5,6] after the code is finished
Can someone help me out here?
Cheers
Ok, my interpretation of your question is that you have a vector that contains CGPoint objects and you want to extract only the y coordinate from all of the points. In that case you want something like (using C++11 lambdas):
std::vector<CGFloat> ycoord;
std::transform( dp->begin(), dp->end(), std::back_inserter( ycoord ),
[]( CGPoint const & p ){ return p.y; } );
If the compiler does not support lambdas, you can write a simple function to perform the extraction:
CGFloat extractY( CGPoint const & p ) {
return p.y;
}
std::transform( dp->begin(), dp->end(), std::back_inserter( ycoord ),
&extractY );
Or functor:
struct extractYfunctor {
CGFloat operator()( CGPoint const & p ) const {
return p.y;
}
};
std::transform( dp->begin(), dp->end(), std::back_inserter( ycoord ),
extractYfuctor() );
If you can use the boost libraries:
std::transform( dp->begin(), dp->end(), std::back_inserter( ycoord ),
boost::bind( &CGPoint::y, _1 ) );
Or with a plain loop:
for ( std::vector< CGPoint >::const_iterator it = dp->begin(); it != dp->end(); ++it ) {
ycoord.push_back( it->y );
}
Your vector is not set up like [2,2,3,3,4,4,5,5,6,6]. It's set up like this: [(2,2),(3,3),(4,4),(5,5),(6,6)]. That is, it's a list of pairs of numbers, not just a list of numbers. To get the y component of each element in the vector, you can write a loop like this:
vector<CGPoint>* dp = xGraph.GraphPoints;
for(i = dp->begin(); i != dp->end(); ++i){
/* grab y points only code here*/
CGFloat current_y = i->y;
}
vector<CGPoint>::iterator i;
vector<CGPoint>* dp = xGraph.GraphPoints;
vector<CGFloat> dp = yPoints;
for(i = dp->begin(); i != dp->end(); ++i){
yPoints.push_back(i->y);
}
vectors are indeed laid out like that in memory, but not logically. Don't overthink things. It's still a vector of CGFloat objects.
I'm trying to figure out the vDSP functions and the results I'm getting are very strange.
This is related to this question:
Using std::complex with iPhone's vDSP functions
Basically I am trying to make sense of vDSP_vdist as I start off with a vector of std::complex< float >. Now AFAIK I should be able to calculate the magnitude by, simply, doing:
// std::abs of a complex does sqrtf( r^2 + i^2 ).
pOut[idx] = std::abs( pIn[idx] );
However when I do this I see the spectrum reflected around the midpoint of the vector. This is very strange.
Oddly, however, if I use a vDSP_ztoc followed by a vDSP_vdist I get exactly the results I expect. So I wrote a bit of code to try and understand whats going wrong.
bool VecMagnitude( float* pOut, const std::complex< float >* pIn, unsigned int num )
{
std::vector< float > realTemp( num );
std::vector< float > imagTemp( num );
DSPSplitComplex dspsc;
dspsc.realp = &realTemp.front();
dspsc.imagp = &imagTemp.front();
vDSP_ctoz( (DSPComplex*)pIn, 1, &dspsc, 1, num );
int idx = 0;
while( idx < num )
{
if ( fabsf( dspsc.realp[idx] - pIn[idx].real() ) > 0.0001f ||
fabsf( dspsc.imagp[idx] - pIn[idx].imag() ) > 0.0001f )
{
char temp[256];
sprintf( temp, "%f, %f - %f, %f", dspsc.realp[idx], dspsc.imagp[idx], pIn[idx].real(), pIn[idx].imag() );
fprintf( stderr, temp );
}
}
return true;
}
Now whats strange is the above code starts failing when idx = 1 and continues to the end. The reason is that dspsc.realp[1] == pIn[0].imag(). Its like instead of splitting it into 2 different buffers that it has straight memcpy'd half the vector of std::complexes into dspsc.realp. ie the 2 floats at std::complex[0] then the 2 floats in std::complex[1] and so on. dspsc.imagp is much the same. dspsc.imagp[1] = pIn[1].real().
This just makes no sense. Can someone explain where on earth I'm failing to understand whats going on?