How to turn the 3D array into 1D array? - c++

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++;
}
}
}
}

Related

Initializing multidimensional dynamical array in c++

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.

Error in output of dynamically initialized 2D array

I'm working on a school project written in c++. I am trying to generate an array of rgb colours based on user input, for a program that generates fractals(irrelevant).
I found the need to use a pointer to a 2D array. The pointer has a global scope because it needs to be accessed across multiple files, in multiple functions.
There is no problem with the declaration of the pointer. It is as such:
in "global.h"
int **ptr;
int palette[10][3];
//all the statements like #ifndef GLOBAL_H_INCLUDED, etc are present
in main.cpp
extern int **ptr;
extern int palette[10][3];
void gen_array();
int main()
{
//initialize values of palette
//palette is basically list of colors that the user selects for the
//desired blend of colors to appear on the screen
gen_array();
}
in void gen_array(), in main.cpp
void gen_array()
{
int i=0, size=0, size_arr=0;
//size is a variable helpful in calculating "size_arr", which is the size of the dynamic array to be initialized
while(palette[i][0]!=256)
{ //calculates "size" }
for(int i=0; i<size-1; i++)
{
//to find "size_arr"
}
ptr= new int*[size_arr]();
for(int i = 0; i < size_arr; ++i)
{
ptr[i] = new int[3];
}
//the following piece of code enter's values column-wise into the array
int s=0;
for(int i=0; i<size-1; i++)
{
for(int k=0; k<3; k++)
{
int x=-1, a=0, b=0;
a= palette[i][k] - palette[i+1][k];
b= palette[i][k];
if(a<0)
{
a= -a;
x=1;
}
for(int j=0; j<=a; j++, s++)
{
ptr[i][k] = b;
//cout<<*(*(ptr+i)+k)<<' ';
b= b+ x;
}
b= b-x;
for(int j=a+1; j<=diff[i]; j++, s++)
{
ptr[i][k] = b;
cout<<ptr[i][k]<<' ';
}
cout<<endl;
}
}
//this output's the array that the pointer points to, on the screen
for(int i=0; i<size_arr; i++)
{
for(int j=0; j<3; j++)
{
cout<<ptr[i][j]<<' ';
}
cout<<endl;
}
}
The problem is that, the data is getting generated and inputted in the array correctly [in the second-last for loop], but when outputting it [the last for loop] I'm getting junk values.
The data inputted [the correct values] as obtained from the cout statements [that are now commented] is this [printed column-wise] whereas the O/P given out is this [printed row-wise].
If it is required to be know, "size" (in this case) =2, size_arr=256 and palette[0]={0, 0, 255} and palette[1]={0,255,0}.
Can anybody point out what the problem is, and whether it has something to do with the pointer initialization?
Even without reading all the program code like
for(int j=0; j<=a; j++, s++)
{
ptr[i][k] = b;
//cout<<*(*(ptr+i)+k)<<' ';
b= b+ x;
}
looks clearly wrong. At each iteration you are writing to ptr[i][k] and the loop doesn't change ptr, i or k. This means that it will keep writing to the very same location during the loop.
Look at your int i in the loop you're using to fill int** ptr. If size = 2 then you're never going to advance ptr far enough to fill the array. Consider filling the array like this:
for(int i = 0; i < size_arr; ++i){//for every pixel in the main array
for(int k = 0; k < 3; ++k){//for every subpixel
int my_value = ...;//calculate the value for this entry
*(*(ptr+i)+k) = my_value;//assign
Better yet, use a struct named pixel containing Uint8 r,g,b and allocate as pixel* ptr = new pixel[size] and iterate over pixels and assign ptr[i].r ptr[i].g ptr[i].b

I get the error invalid types 'float[int]' for array subscript?

I am quite new to programming,so I really need help. I need to wrtie a function which produce 2d arrays with random values. here is my code:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
float randArray(int row, int column);
int main()
{
int r = 10, c = 8;
float fckMmd = randArray(r,c);
///printing the array:
for (int row=0; row<r; row++){
for (int column=0; column<c; column++){
cout << fckMmd[row][column] << " ";
}
cout << endl;
}
}
float randArray(int row, int column){
srand(time(NULL));
float *randArr;
randArr = new int [row][column];
for(int k=0; k<row; k++){
for(int kk=0; kk<column; kk++){
randArr[k][kk] = rand();
}
}
return randArr;
}
But I get the error mentioned above. Where is the problem? help me please
randArr is a float * but you try to allocate a 2d array in it. A 2d array is not the same thing as a pointer. Your function only returns 1 float as well. I suggest you use vectors (also so you don't leak memory). Furthermore you should only call srand ONCE, not every time, and be aware rand() returns an integer, not a floating point value.
std::vector<std::vector<float>> randArray(int row, int column)
{
std::vector<std::vector<float>> randArr(row);
for (auto& v : randArr)
{
v.resize(column);
}
for(int k=0; k<row; k++)
{
for(int kk=0; kk<column; kk++)
{
randArr[k][kk] = static_cast<float>(rand());
}
}
return randArr;
}
It's because fckMmd is only a float and not a pointer or array.
First:
float *randArr;
declares a pointer to float. You then do
randArr = new int [row][column];
which allocates memory for a 2D array of ints (incompatible types, technically you allocate memory for a pointer to arrays of type int[column]), hence the error.
You're better using a std::vector instead, or, if you want a manually-managed dynamically allocated 2D array, use float **randArr; instead, and allocate
float** randArr;
randArr = new float* [rows];
for(int i = 0; i < row; ++i)
randArr[i] = new float[col];
or
float (*randArr)[col]; // pointer to array float[col]
randArr = new float[row][col];
Other issues: most of the time, srand must be used only once in the program. It is a good idea to call it in main() and not bury it into a function, since you may end up calling the function multiple times.
Last issue: if you want speed, you're better off using a single flat array (or std::vector) and map from 2D to 1D and vice versa, since your data will be guaranteed to be contiguous and you'll have very few cache misses.

C++, how can I make a dynamic 3D matrix?

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.

Dynamic 2D Array Initialization

I want to create and initialize a 2D array but the initialization is failed. I encounter "The program has unexpectedly finished." in Qt Creator.
What is wrong?
in .h file
private:
int pop;
int d;
float **uye;
in .cpp file
pop=50;
d=12;
uye = new float*[pop];
for(int i=0; i<d; i++) uye[i] = new float[d];
for(int n=0; n<pop; n++)
{
for(int m=0; m<d; m++)
{
uye[n][m] = (float) n*m;
}
}
The first loop for(int i=0; i<d; i++) should probably be for(int i=0; i<pop; i++). Otherwise, you are only reserving space for 12 elements, but later try to access 50.
Note that having raw pointer members is considered a very bad idea in modern C++, because you need to worry about copying semantics. Better use a flat std::vector<float> and do the 2D to 1D mapping manually, or use a std::vector<std::vector<float> > with convenient access syntax.
I would prefer the second version. Without seeing more context:
pop = 50;
d = 12;
uye = std::vector<std::vector<float> >(pop, std::vector<float>(d));
The nested for loops that follow work exactly the same, no changes required.
What is wrong?
You're not using std::vector (that's one of the things that's wrong, #FredO covered the other thing).
#include <vector>
int main(){
typedef std::vector<float> inner_vec;
typedef std::vector<inner_vec> outer_vec;
int pop = 50, d = 12;
// first parameter to vector is its size
// second is what every element should be initialized to
outer_vec uye(pop, inner_vec(d));
for(unsigned n = 0; n < uye.size(); ++n){
for(unsigned m = 0; m < uye[n].size(); ++m){
uye[n][m] = (float)n*m;
}
}
}