iterate over std::vector of std::vector [duplicate] - c++

I'm trying to pass a variable of type vector<vector<double> > to a function F(double ** mat, int m, int n). The F function comes from another lib so I have no option of changing it. Can someone give me some hints on this? Thanks.

vector<vector<double>> and double** are quite different types. But it is possible to feed this function with the help of another vector that stores some double pointers:
#include <vector>
void your_function(double** mat, int m, int n) {}
int main() {
std::vector<std::vector<double>> thing = ...;
std::vector<double*> ptrs;
for (auto& vec : thing) {
// ^ very important to avoid `vec` being
// a temporary copy of a `thing` element.
ptrs.push_back(vec.data());
}
your_function(ptrs.data(), thing.size(), thing[0].size());
}
One of the reasons this works is because std::vector guarantees that all the elements are stored consecutivly in memory.
If possible, consider changing the signature of your function. Usually, matrices are layed out linearly in memory. This means, accessing a matrix element can be done with some base pointer p of type double* for the top left coefficient and some computed linear index based on row and columns like p[row*row_step+col*col_step] where row_step and col_step are layout-dependent offsets. The standard library doesn't really offer any help with these sorts of data structures. But you could try using Boost's multi_array or GSL's multi_span to help with this.

The way I see it, you need to convert your vector<vector<double> > to the correct data type, copying all the values into a nested array in the process
A vector is organised in a completely different way than an array, so even if you could force the data types to match, it still wouldn't work.
Unfortunately, my C++ experience lies a couple of years back, so I can't give you a concrete example here.

Vector< Vector< double> > is not nearly the same as a double pointer to m. From the looks of it, m is assumed to be a 2-dimensional array while the vector is could be stored jagged and is not necessarily adjacent in memory. If you want to pass it in, you need to copy the vector values into a temp 2dim double array as pass that value in instead.

Related

How to convert column vector into MxN matrix?

I am relatively new to C++ and kind of stuck in this problem. I have 999x1 vector of point coordinates and I want to convert it in 333x3 matrix dyanamically. Besides this, I am using different Cpp files for one project so the function which reads the points set is in different file. How to make this matrix and how should I access it in my main code?
I tried using vector<vector<float> > Mymatrix thing but you need to specify the rows and column size in this kind of definition which I cannot get until I read the file. If I try to declare above Mymatrix variable in the function which is reading the pointset file, its scope gets limited and I cannot use that Mymatrix in main.cpp.
Its little bit difficult to write the code here because it has many links with other files. I hope you have got my problem! Please help me in this issue...Thanks in advance!
vector is really just a container for array. So basically what you have is a int A[999] and want to convert this into int M[333][3];
Considering that in memory both a 1D and a 2D array are stored in a contiguous memory region, you can achieve this in several ways:
- use a pointer and two indexes i, j: the first 3 elements are your first row,
the next 3 elements your second row and so on.
int vector<int> v;
int *p, i=0,j=0; // i=[0..332], j=[0..2]
p=&v[0];
*(p+(i*3)+j); //this is the same as p[i][j];
Or declare matrix (either allocate static or dynamic memory for it) and copy all the elements int the matrix:
int M[333][3]; //i'll go with static allocation for this example
for(i=0;i<333;i++)
for(j=0;j<3;j++)
M[i][j] = v[i*3 + j];
choose which ever method you want - the advantage of the first one is that it does not us the extra memory.
You can create your MyMatrix as a pointer and pass to your function as parameter:
vector<vector<float> >* Mymatrix; //Don't forget to initialize the pointer
functionThatReadsFiles(Mymatrix); //That function makes changes to Mymatrix
With this, any changes you make to Mymatrix inside "functionThatReadsFiles" will remain after its call. Anyway, make sure you fully understand how to operate with pointers before trying this.
As #erlc says, you can also declare your function with:
void functionThatReadsFiles(vector<vector<float> >& Mymatrix);
And call just call it normally (without pointers), and again the changes will remain into your Mymatrix.

1D Vector to Multi-dimensional array / Vector

I have a 1D dimensional vector of floats I just read in from a file.
std::vector<float> result(s.size() / sizeof(float));
I want to use this data like this
myTable[rl][gl][bl][0];
So is there any easy way to convert my 1D vector to a multidimensional vector or multidimensional array that is simple?
float myTable[100][10][20][30];
vector<vector<vector<vector<int> >>> myTable;
Where I can still easily use the indexing that is setup all over the code.
and not have to convert it to a 1D access like : myTable[indexmathhere]
I wouldn't actually rewrite the data, unless you have cache requirements (though we don't know anything about the layout of your data).
Store the vector inside a class, and write an accessor function that takes four index arguments and performs the necessary arithmetic to flatten them into the single vector index.
class MyMatrix
{
std::vector<float> result;
public:
float at(int r, int g, int b, int a) const
{
return result[r+W*g+W*H*b+W*H*D*a]; // or whatevs
}
};
You could even write some operator() overloads, but you'd need three proxy types to get four dimensions of indexing out of that.
If you have fixed size array you probably should use std::array.
Something like it is in this question: Multidimensional std::array
Unfortunately, there is no oneliner to put your data into this array, you need to do it manually.

Making only the outer vector in vector<vector<int>> fixed

I want to create a vector<vector<int>> where the outer vector is fixed (always containing the same vectors), but the inner vectors can be changed. For example:
int n = 2; //decided at runtime
assert(n>0);
vector<vector<int>> outer(n); //outer vector contains n empty vectors
outer.push_back(vector<int>()); //modifying outer vector - this should be error
auto outer_it = outer.begin();
(*outer_it).push_back(3); //modifying inner vector. should work (which it does).
I tried doing simply const vector<vector<int>>, but that makes even the inner vectors const.
Is my only option to create my own custom FixedVectors class, or are there better ways out there to do this?
by definition,
Vectors are sequence containers representing arrays that can change in
size. Just like arrays, vectors use contiguous storage locations for
their elements, which means that their elements can also be accessed
using offsets on regular pointers to its elements, and just as
efficiently as in arrays. But unlike arrays, their size can change
dynamically, with their storage being handled automatically by the
container.
if you aren't looking to have a data structure that changes in size, a vector probably isn't the best choice for an outer layer, How about using an array of vectors. This way the array is of a fixed size and cannot be modified, while still having the freedom of having its size declared in runtime.
vector<int> *outer;
int VectSize;
cout >> "size of vector array?"
cin >> VectSize;
outer = new vector<int>[VectSize]; //array created with fixed size
outer.push_back() //not happening
Wrap the outer vector into a class which just provides at, begin, end and operator []. Let the class take only have one constructor taking its capacity.
This most probably the best way.
const vector<unique_ptr<vector<int>>> outer = something(n);
For the something, you might write a function, like this:
vector<unique_ptr<vector<int>>> something(int n)
{
vector<unique_ptr<vector<int>>> v(n);
for (auto & p : v)
p.reset(new vector<int>);
return v;
}

How to Implement a multidimensional array if the dimension is unknown at compile-time?

I want to implement a function that gets as a parameter a dimension "n" of an array of integers. This function also gets values "k_1, k_2, ..., k_n" defining the size of the array. Then this function will fill this n-dimensional array.
How do I implement this efficiently with C++?
For example for n = 3 I would use
vector < vector < vector < int > > > array;
But I don't know the dimension at compile time.
Use a one-dimensional array, and fake the other dimensions using multiplication of offsets for indexing, and you can pass the dimension sizes in by vector, i.e.
std::vector<int> create_md_array(const std::vector<int> & dimensions)
{
int size = std::accumulate(dimensions.begin(), dimensions.end(), 1, std::multiplies<int>());
return std::vector<int>(size);
}
You have a couple of choices. You can implement it yourself, basically multiplying the coordinates by the sizes to linearize the multi-dimensional address, and just have a simple std::vector<whatever> to hold the data.
Alternatively, you could use std::valarray and friends to accomplish the same. It has a set of classes that are specifically intended for the kind of situation you describe -- but they're used so rarely that almost nobody understands them. Writing the code yourself stands a good chance of being easier for most people to read and understand.

pointer arithmetic on vectors in c++

i have a std::vector, namely
vector<vector<vector> > > mdata;
i want pass data from my mdata vector to the GSL function
gsl_spline_init(gsl_spline * spline, const double xa[], const double ya[], size_t size);
as ya. i already figured out that i can do things like
gsl_spline_init(spline, &(mgrid.front()), &(mdata[i][j][k].front()), mgrid.size());
this is fine if i want to pass the data from mdata for fixed i,j to gsl_spline_init().
however, now i would need to pass along the first dimension of mdata, so for fixed j,k.
i know that for any two fixed indices, all vectors along the remaining dimensions have the same length, so my vector is a 'regular cube'. so the offset between all the values i need should be the same.
of course i could create a temporary vector
int j = 123;
int k = 321;
vector<double> tmp;
for (int i = 0: i < mdata.size(); i++)
tmp.push_back(mdata[i][j][k]);
gsl_spline_init(spline, &(mgrid.front()), &(tmp.front()), mgrid.size());
but this seems too complicated. perhaps there is a way to achieve my goal with pointer arithmetic?
any help is greatly appreciated :)
You really can't do that without redesigning the array consumer function gsl_spline_init() - it relies on the data passed being a contiguous block of data. This is not the case with you three-level vector - not only it is a cube but also each level has a separate buffer allocated on heap.
This can't be done. Not only with vectors, but even with plain arrays only the last dimension is a contiguous block of data. If gsl_spline_init took an iterator instead of array, you could try to craft some functor to choose appropriate data but I'm not sure it's worth trying. No pointer arithmetic can help you.