In C++, Codeblocks environment, I declared:
int m[120][120][120];
I know that from m[0][0][0] to m[119][119][119] I have variables.
Can I make the computer to start declaring memory from positions m[45][45][45]?
I hope I made myself clear :)
If you just need 45..119 just make your matrix 45 smaller in each dimension and convert the values
// Very simple example to explain what I meant.
class MyMatrix
{
public:
SetValue(int x, int y, int z, float value) { mMatrix[x-45][y-45][z-45] = value; }
private
float mMatrix[120-45][120-45][120-45];
}
What you say is basically reserving/allocating some memory at the beginning, and if later on you needed more memory, you want it to be extended.
If that's the case, you'd better use std::vector, and pass 45 as the initial capacity. Usually 45 is too small, but if you want to set it anyway, you can do it through std::vector.reserve(n) method. It would be something like this:
matrix = vector<vector<vector<float> > >();
matrix.reserve(45);
for (int i = 0; i < 45; i++)
{
matrix[i] = vector<vector<float> >()
matrix[i].reserve(45);
for (int j = 0; j < 45; j++)
{
matrix[i][j] = vector<float>();
matrix[i][j].reserve(45);
}
}
You can also achieve the same thing using the fill constructor, as described here.
Related
Probably a very simple thing, but I am new to C++, Eigen, etc.
I have a MatrixXD with n rows. Each row holds 3 points (x,y,z) and I have a function that takes a vector3d type pointer as an input. I want to iterate over all rows n of the MatrixXd and use pass each row as a vector to my function.
I assume it is a combination of accessing the MatrixXd pointers - maybe with something like this:
int r = mydata.rows();
int c = mydata.cols();
for (int i = 0; i < r; ++i)
{
for (int j = 0; j < c; ++j)
{
myObject.myfunction(&mydata(i,j));
}
}
and using the returned pointers to call my function on each of the rows i.e. for each iteration.
Update 1:
This seems it might work. However, I need to have mydata(i,j) return pointers instead of the data.
Another problem I think I can see: In the current form, I think this is just returning the elements at i,j but I actually need to return a pointer to a Vector3D. Might data.row(i) work for that?
Update 2:
Something like this might be more what I need. Still not working though. I removed the & - which makes sense - and it's working now.
int r = data.rows();
int c = data.cols();
for (int i = 0; i < r; ++i)
{
myObject.myFunction(data.row(i));
}
Can you give me some idea if I am going down the right road, on how to approach this or what other details you would need to help me more?
Solved. The above-posted code works for me.
int r = data.rows();
int c = data.cols();
for (int i = 0; i < r; ++i)
{
myObject.myFunction(data.row(i));
}
I have a big problem, i want to put a matrix pointer of objects to a function but i don't know how can do this, the objects that i use they are from derived class. This is an example of my code. Note: class Piece is a base class and class Queen is a derived class from Piece
#include "Queen.h"
void changeToQueen(Piece* mx)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
mx[i][j] = new Queen();
}
}
}
int main()
{
Piece * matrix[7][7];
changeToQueen(matrix); // this fails
return 0;
}
You can change the input argument to void changeToQueen(Piece * mx[7][7]).
Or you can change the input argument to void changeToQueen(Piece** mx).
Change the assignment operator to mx[7*i + j] = new Queen(); and pass in the first element as input changeToQueen(&(matrix[0][0]));
The reason why both work is because multidimensional array elements are stored contiguously in memory. So all you need is a pointer to the first element.
Both solutions are a bit flawed because if you need to change the dimensions of your matrix, you have to change your code a bit. Changing your prototype to void changeToQueen(Piece** mx, size_t width, size_t height) will be helpful for the future.
Alternatively this could be a way to handle things
template <unsigned int rows, unsigned int columns>
class Board
{
public:
Board() {}
void changeToQueen()
{
for (unsigned int y = 0 ; y < rows ; ++y)
{
for (unsigned int x = 0 ; x < columns ; ++x)
{ _pieces[y][x] = Queen(); }
}
}
Piece &at(unsigned int row, unsigned int column)
{ return _pieces[row][column]; } // you should check for out of range
// you could either have a default null value for Piece to return, or throw an exception
private:
Piece _pieces[rows][columns];
};
int main()
{
Board<8,8> board;
board.changeToQueen();
// return 0; // this is not mandatory in c++
}
So, yeah, no pointers almost no worries ;)
You still want pointers?? uhm... okay maybe you could do that: Piece *_pieces[rows][columns];, i'm not sure you really need it, but I can't tell how much it would modify your existing code to do this.
First of all, I do not understand dependencies between Queen and Piece, so I suppose that Piece is super-type of Queen and assignment Piece * mx = new Queen(); is correct.
To fix the obvious problem of type mismatch you can change your
void changeToQueen(Piece* mx)
to
void changeToQueen(Piece* mx[7][7])
and with changing loops border to 7 (for (int i = 0; i < 7; i++)) or size of matrix to 8 x 8 (with the same loops) this will work.
But my suggestion is to think over method of storing data.
Perhaps you will need to build matrix of size different from 7x7, so consider the following example, where dynamic memory is used to store the matrix (in this example only Queen is used):
void changeToQueen(Queen*** &mx, int size)
{
mx = new Queen**[size]; // allocation of memory for pointers of the first level
for (int i = 0; i < size; i++)
{
mx[i] = new Queen*[size]; // allocation of memory for pointers of the second level
for (int j = 0; j < size; j++)
{
mx[i][j] = new Queen(); // allocation of memory for object
}
}
}
int main()
{
int m_size = 7;
Queen *** matrix = NULL; // now memory not allocated for matrix
changeToQueen(matrix, m_size);
return 0;
}
Note: & sign in void changeToQueen(Queen*** &mx, int size) allows to change pointer Queen *** matrix; inside the function changeToQueen
I'm having problems declaring a multidimensional dynamical array in c style. I want to declare dynamically an array like permutazioni[variable][2][10], the code i'm using is as following (carte is a class i defined):
#include "carte.h"
//other code that works
int valide;
carte *** permutazioni=new carte**[valide];
for (int i=0; i<valide; i++){
permutazioni[i]=new carte*[2];
for (int j=0; j<2; j++) permutazioni[i][j]=new carte[10];
}
the problem is, whenever i take valide=2 or less than 2, the code just stops inside the last for (int i=0; i<valide; i++) iteration, but if i take valide=3 it runs clear without any problem. There's no problem as well if i declare the array permutazioni[variable][10][2] with the same code and any value of valide. I really have no clue on what the problem could be and why it works differently when using the two different 3d array i mentioned before
You show a 3D array declared as permutazioni[variable][10][2] but when you tried to dynamical allocate that you switched the last two dimensions.
You can do something like this:
#include <iostream>
#define NVAL 3
#define DIM_2 10 // use some more meaningfull name
#define DIM_3 2
// assuming something like
struct Card {
int suit;
int val;
};
int main() {
// You are comparing a 3D array declared like this:
Card permutations[NVAL][DIM_2][DIM_3];
// with a dynamical allocated one
int valid = NVAL;
Card ***perm = new Card**[valid];
// congrats, you are a 3 star programmer and you are about to become a 4...
for ( int i = 0; i < valid; i++ ){
perm[i] = new Card*[DIM_2];
// you inverted this ^^^ dimension with the inner one
for (int j = 0; j < DIM_2; j++)
// same value ^^^^^
perm[i][j] = new Card[DIM_3];
// inner dimension ^^^^^
}
// don't forget to initialize the data and to delete them
return 0;
}
A live example here.
Apart from that it is always a good idea to check the boundaries of the inddecs used to access to the elements of the array.
How about using this syntax? Haven't tested fully with 3 dimensional arrays, but I usually use this style for 2 dimensional arrays.
int variable = 30;
int (*three_dimension_array)[2][10] = new int[variable][2][10];
for(int c = 0; c < variable; c++) {
for(int x = 0; x < 2; x++) {
for(int i = 0; i < 10; i++) {
three_dimension_array[c][x][i] = i * x * c;
}
}
}
delete [] three_dimension_array;
Obviously this could be c++ 11/14 improved. Could be worth a shot.
In my code, I defined a 3D array to store the date on CUDA kernel.The code just like this:
if(k<2642){
double iCycle[100], jCycle[100];
int iCycleNum = 0, jCycleNum = 0;
for(double i=0; i<=1; i+=a, ++iCycleNum){
iCycle[iCycleNum] = i;
for(double j=0; j+i<=1; j+=c, ++jCycleNum){
jCycle[jCycleNum] = j;
[...]
r=(int)color[indexOutput];
g=(int)color[indexOutput+1];
b=(int)color[indexOutput+2];
d_RGB[k][iCycleNum][jCycleNum].x=r;//int3 (*d_RGB)[100][100]
d_RGB[k][iCycleNum][jCycleNum].y=g;
d_RGB[k][iCycleNum][jCycleNum].z=b;
}
}
}
In every cycle, there is an r,g,b. I want to store the r,g,b in d_RGB[k][iCycleNum][jCycleNum],then I need to pass them to the host. But in this case, every k has a different iCycleNum and jCycleNum, and I do not know the value of them, so the 3D array here is so awaste of space and may be it could bring some bugs. I wonder if it is a way to change the 3D array into a 1D one like this: d_RGB[k+iCycleNum*x+jCycleNum*x*y].
Sorry, my English is not so good to decribe it clearly, so if you can not get what I mean, please add a comment. Thank you.
Actually a "classic" 3D array is organized in the memory as a 1D array (since the memory is 1D oriented).
The Code:
int aiTest[5][5][5] = {0};
int* piTest = (int*)aiTest;
for (int i = 0; i < 125; i++)
{
piTest[i] = i;
}
does not make any memory violations - and the element aiTest[4][4][4] will have the value of 124.
So the answer: just cast it to the right type you need.
int arr[5][6][7];
int resultant_arr[210];
int count=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<6;j++)
{
for(int k=0;k<7;k++)
{
if(count<210)
{
resultant_arr[count]=arr[i][j][k];
count++;
}
}
}
}
I am having a tough time getting my head wrapped around how to initialize a vector of vectors.
typedef vector< vector < vector < vector< float > > > > DataContainer;
I want this to conform to
level_1 (2 elements/vectors)
level_2 (7 elements/vectors)
level_3 (480 elements/vectors)
level_4 (31 elements of float)
Addressing the elements isn't the issue. That should be as simple as something like
dc[0][1][2][3];
The problem is that I need to fill it with data coming in out of order from a file such that successive items need to be placed something like
dc[0][3][230][22];
dc[1][3][110][6]; //...etc
So I need to initialize the V of V beforehand.
Am I psyching myself out or is this as simple as
for 0..1
for 0..6
for 0..479
for 0..30
dc[i][j][k][l] = 0.0;
It doesn't seem like that should work. Somehow the top level vectors must be initialized first.
Any help appreciated. I am sure this must be simpler than I am imagining.
Please do not use nested vectors if the size of your storage is known ahead of time, i.e. there is a specific reason why e.g. the first index must be of size 6, and will never change. Just use a plain array. Better yet, use boost::array. That way, you get all the benefits of having a plain array (save huge amounts of space when you go multi-dimensional), and the benefits of having a real object instantiation.
Please do not use nested vectors if your storage must be rectangular, i.e. you might resize one or more of the dimensions, but every "row" must be the same length at some point. Use boost::multi_array. That way, you document "this storage is rectangular", save huge amounts of space and still get the ability to resize, benefits of having a real object, etc.
The thing about std::vector is that it (a) is meant to be resizable and (b) doesn't care about its contents in the slightest, as long as they're of the correct type. This means that if you have a vector<vector<int> >, then all of the "row vectors" must maintain their own separate book-keeping information about how long they are - even if you want to enforce that they're all the same length. It also means that they all manage separate memory allocations, which hurts performance (cache behaviour), and wastes even more space because of how std::vector reallocates. boost::multi_array is designed with the expectation that you may want to resize it, but won't be constantly resizing it by appending elements (rows, for a 2-dimensional array / faces, for a 3-dimensional array / etc.) to the end. std::vector is designed to (potentially) waste space to make sure that operation is not slow. boost::multi_array is designed to save space and keep everything neatly organized in memory.
That said:
Yes, you do need to do something before you can index into the vector. std::vector will not magically cause the indexes to pop into existence because you want to store something there. However, this is easy to deal with:
You can default-initialize the vector with the appropriate amount of zeros first, and then replace them, by using the (size_t n, const T& value = T()) constructor. That is,
std::vector<int> foo(10); // makes a vector of 10 ints, each of which is 0
because a "default-constructed" int has the value 0.
In your case, we need to specify the size of each dimension, by creating sub-vectors that are of the appropriate size and letting the constructor copy them. This looks like:
typedef vector<float> d1;
typedef vector<d1> d2;
typedef vector<d2> d3;
typedef vector<d3> d4;
d4 result(2, d3(7, d2(480, d1(31))));
That is, an unnamed d1 is constructed of size 31, which is used to initialize the default d2, which is used to initialize the default d3, which is used to initialize result.
There are other approaches, but they're much clumsier if you just want a bunch of zeroes to start. If you're going to read the entire data set from a file, though:
You can use .push_back() to append to a vector. Make an empty d1 just before the inner-most loop, in which you repeatedly .push_back() to fill it. Just after the loop, you .push_back() the result onto the d2 which you created just before the next-innermost loop, and so on.
You can resize a vector beforehand with .resize(), and then index into it normally (up to the amount that you resized to).
You would probably have to set a size or reserve memory
Could you do a for-each or a nested for that would call
myVector.resize(x); //or size
on each level.
EDIT: I admit this code is not elegant. I like #Karl answer which is the right way to go.
This code is compiled and tested. It printed 208320 zeroes which is expected (2 * 7 * 480 * 31)
#include <iostream>
#include <vector>
using namespace std;
typedef vector< vector < vector < vector< float > > > > DataContainer;
int main()
{
const int LEVEL1_SIZE = 2;
const int LEVEL2_SIZE = 7;
const int LEVEL3_SIZE = 480;
const int LEVEL4_SIZE = 31;
DataContainer dc;
dc.resize(LEVEL1_SIZE);
for (int i = 0; i < LEVEL1_SIZE; ++i) {
dc[i].resize(LEVEL2_SIZE);
for (int j = 0; j < LEVEL2_SIZE; ++j) {
dc[i][j].resize(LEVEL3_SIZE);
for (int k = 0; k < LEVEL3_SIZE; ++k) {
dc[i][j][k].resize(LEVEL4_SIZE);
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
dc[i][j][k][l] = 0.0;
}
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
cout << dc[i][j][k][l] << " ";
}
}
}
}
cout << endl;
return 0;
}