Thread: How to make this "for loop"

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    8

    How to make this "for loop"

    Hi. I made a function in Matlab for image processing (with 256x256 arrays), but it contains a "for loop" that make it slow. So I think it'd be faster in c++, but i'm just a beginner and i don't know how to work with 2D arrays.

    My Matlab code is:
    Code:
    [data2]=functionx(data,fx,fy) //data2 is an output array 256x256; data,fx,fy are 256x256 inputs
    [Lx,Ly]=size(data); //Lx is number of rows, Ly columns
    data2 = zeros(Lx,Ly); //preallocate an array 2D
    
    for x = 1:Lx-1
       for y = 1:Ly-1       
          
          dx = x + fx(x,y);
          dy = y + fy(x,y);
          
          ix = floor(dx); //floor rounds the element dx to the nearest integer towards minus infinity
          iy = floor(dy);
          
          ax = 1 - (dx - ix);
          ay = 1 - (dy - iy);
          
          
          if ix>0 & iy>0 & ix<Lx & iy<Ly
             data2(x,y) = ax*ay*data(ix,iy) + (1-ax)*ay*data(ix+1,iy) + ax*(1-ay)*data(ix,iy+1) + (1-ax)*(1-ay)*data(ix+1,iy+1);
          end
       end
    end
    Well, it isn't a difficult code and i don't ask for all it, only how to work with 2D arrays (create 2D arrays, arrays sum, access to a value). Thanks a lot for your time.

  2. #2
    Registered User
    Join Date
    Jan 2008
    Posts
    45
    This doesn't really look like C++ imho.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, the original post says that it's "matlab", which has somewhat different syntax. I believe the following:
    Code:
    for x = 1:Lx-1
    translates to C (or C++) as:
    Code:
    int x;
    for(x = 1; x <= Lx-1; x++)
    Code:
    ax*ay*data(ix,iy)
    would be:
    ax*ay*data[ix][iy];
    [/code]

    And you would declare data[] and data2[] as this:
    Code:
    double data[Lx][Ly];
    double data2[Lx][Ly];
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Sep 2008
    Posts
    8
    Quote Originally Posted by matsp View Post

    And you would declare data[] and data2[] as this:
    Code:
    double data[Lx][Ly];
    double data2[Lx][Ly];
    --
    Mats
    Hi Mats. Thanks for your answer. The problem is that data is an input array, so I have to put their values to a new array, or do i have to use a pointer to this array?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by kurko82 View Post
    Hi Mats. Thanks for your answer. The problem is that data is an input array, so I have to put their values to a new array, or do i have to use a pointer to this array?
    Depends on whether you want the original data to remain the same, or it's ok to write back the result to the old array. Looking at this:
    Code:
    data2(x,y) = ax*ay*data(ix,iy) + (1-ax)*ay*data(ix+1,iy) + ax*(1-ay)*data(ix,iy+1) + (1-ax)*(1-ay)*data(ix+1,iy+1);
    , it looks like you MAY use the same positions in data[x][y] more than once, so you have to retain the old value until you are completely finished.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Here are some basic things you might want to know:
    Create:
    1) You create the array by declaring it (like mastp noted). You should keep in mind that you might need to dynamically allocate it (with new), but that is a different story, which I don't think you mind at the moment.
    Assign:
    2) You access a value with the [][] symbols. Like array[10][2] is the element on the 11th line and 3nd row. Note that arrays in C/C++ start from ZERO!
    Sum:
    3) To sum the values of an array you just have to make a function. If you want something particular ask. I don't know exactly what you mean by sum array (sum every value, sum every value of each line and return a vector?). In any case here is a function that sums every value and returns a double (floating number with double precision) with the result
    Code:
    double sum2DArray(double **array, int rows, int columns) {
       double sum = 0;
       for (int i=0; i<rows; ++i)
          for (int j=0; j<columns; ++j)
                sum += array[i][j];
       return sum;
    }
    
    //Use it like this
    double data[100][10]; //declare the 2D array
    double sum; //declare the integer that holds the sum
    sum = sum2DArray9(data, 100, 10); //assign to sum the sum of the array

  7. #7
    Registered User
    Join Date
    Sep 2008
    Posts
    8
    Quote Originally Posted by matsp View Post
    Depends on whether you want the original data to remain the same, or it's ok to write back the result to the old array. Looking at this:
    Code:
    data2(x,y) = ax*ay*data(ix,iy) + (1-ax)*ay*data(ix+1,iy) + ax*(1-ay)*data(ix,iy+1) + (1-ax)*(1-ay)*data(ix+1,iy+1);
    , it looks like you MAY use the same positions in data[x][y] more than once, so you have to retain the old value until you are completely finished.

    --
    Mats
    lol, thanks for your answer and for your correction (have to -> may, i may improve my english).
    Well, data2 is an output array and its values are added each "for loop" iteration, and data is only for reading values. So, how could I write this line code?

    Another question. I'm writing a Mexfile, so code works with MxArray. To pass the values of an input MxArray to an array2D, is it possible this code?

    Code:
    typedef double TIPO;       // macros before main
    typedef TIPO** IMAGEN;
    
    
    //rowsT and columnsT are the size
    
    data2 = new TIPO* [rowsT];       // It creates output array
    for (i = 0; i < rowsT; ++i)       
    data2[i] = new TIPO [columnsT];
    
    //Write mxArray data to array2D data2
    salida = mxGetPr(Tu_ptr); //I think this isn't correct, because i'm very bad with pointers

  8. #8
    Registered User
    Join Date
    Sep 2008
    Posts
    8
    Quote Originally Posted by C_ntua View Post
    Here are some basic things you might want to know:
    Create:
    1) You create the array by declaring it (like mastp noted). You should keep in mind that you might need to dynamically allocate it (with new), but that is a different story, which I don't think you mind at the moment.
    Assign:
    2) You access a value with the [][] symbols. Like array[10][2] is the element on the 11th line and 3nd row. Note that arrays in C/C++ start from ZERO!
    Sum:
    3) To sum the values of an array you just have to make a function. If you want something particular ask. I don't know exactly what you mean by sum array (sum every value, sum every value of each line and return a vector?). In any case here is a function that sums every value and returns a double (floating number with double precision) with the result
    Code:
    double sum2DArray(double **array, int rows, int columns) {
       double sum = 0;
       for (int i=0; i<rows; ++i)
          for (int j=0; j<columns; ++j)
                sum += array[i][j];
       return sum;
    }
    
    //Use it like this
    double data[100][10]; //declare the 2D array
    double sum; //declare the integer that holds the sum
    sum = sum2DArray9(data, 100, 10); //assign to sum the sum of the array
    OK, you are right, I explained it better last message. My problem with arrays come when I try to write in array2D all MxArray values. MxArray is a double matrix(array2D). And thanks for your sum code, it will be useful for me

  9. #9
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Just to add that you still need to declare data2 (if you hadn't already). You could do both the allocation and declaration in one line like this:
    Code:
    double** data2 = new TIPO* [rowsT];
    
    //or
    
    IMAGEN data2 = new TIPO* [rowsT];
    
    //or in two lines
    
    double** data2;
    data2 = new TIPO* [rowsT];
    As for your question the way you do it is fine. Just replace data2(x,y) with data2[x][y] etc etc and your code is fine.

    Unfortunately, I know nothing about mexFile so cannot help you there.

  10. #10
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    So mxArray is a 2D array of doubles. And data2 is a 2D array of doubles. Correct? In order to copy one array to another you just assign each individual value with a double for loop. That is the only way. Now, I ll give you a function for that, since I have some minutes to kill
    Code:
    void copy2DArray (double** input, double** output, int rows, int columns)
    {
       for (int i=0; i<rows; ++i)
          for (int j=0; j<columns; ++j)
             output[i][j] = input[i][j];
    }
    The above code copies the array input to the array output. So copy2DArray(data, data2, rowsT, columnsT) will copy each value of data to data2. More specific it will copy the subarray defined by the rows, columns parameters of the function.
    Now. If you want a function that creates a copy (thus,also allocates) then here is one:
    Code:
    double** copy2DArray (double** input, int rows, int columns)
    {
       double** output = new double* [rows];
       double* temp = new double[rows*columns];
       for (int i=0; i<rows; ++i)
          output[i] = temp+i*columns;
       for (int i=0; i<rows; ++i)
          for (int j=0; j<columns; ++j)
             output[i][j] = input[i][j];
       return output;
    }
    Now, you can create a 2D array like this. It will be initialized with the values of data[][]
    Code:
    double** data2 = copy2DArray(data, rowsT, columnsT);
    Note: I used another method of dynamically allocating ouput inside copy2DArray. A bit more complicated but it should be a bit more efficient (details details).

    EDIT: You might have some problems with the above code if the input data is not allocated with the new operator, since the type of double** and double[][] will conflict. I ll see into this if that is the kind of function you want
    Last edited by C_ntua; 09-22-2008 at 03:29 PM.

  11. #11
    Registered User
    Join Date
    Sep 2008
    Posts
    8
    Ok thanks for your answers. I finally did it

    Code:
    for (int x = 0; x < rows; x++){
        for(int y = 0; y < cols; y++){
    
           data2[x * cols + y] = ax*ay*data[x * cols + y] + .....
    
       }
    }

  12. #12
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Nice A little better way is to use a macro to do this. Adding this code, preferably under the declaration of data2:
    Code:
    #define data2(x,y)  data2[(x) *cols + (y)]
    will let you use the index as in matlab. This is actually a common "trick" in order to define multidimensional arrays in the form of a fucntion (parenthesis instead of []). data2 will actually be a 1D array, but you will use it, like data(x,y), with a 2D indexing. This will make simpler also the allocation for example, as it is actually a 1D array than a 2D.
    It is exactly the same as your code, it will just help you right faster the indexing and be far more undertandable than [x*cols +y].

    Just to add, even though I said this before, that in C the index starts from 0, but in matlab it starts from 1. For just the for-loop is fine, but since you use the x,y in your matlab code, make sure that you get the desired results for x = 0 and y = 0. The same for the upper bounds that might be one less.

    In any case, you can pretend that the arrays start from 1 also in C and just ignore the very first element. That will guarantee that you won't have a bug by changing the index.

  13. #13
    Registered User
    Join Date
    Sep 2008
    Posts
    8
    Quote Originally Posted by C_ntua View Post
    Nice A little better way is to use a macro to do this. Adding this code, preferably under the declaration of data2:
    Code:
    #define data2(x,y)  data2[(x) *cols + (y)]
    will let you use the index as in matlab. This is actually a common "trick" in order to define multidimensional arrays in the form of a fucntion (parenthesis instead of []). data2 will actually be a 1D array, but you will use it, like data(x,y), with a 2D indexing. This will make simpler also the allocation for example, as it is actually a 1D array than a 2D.
    It is exactly the same as your code, it will just help you right faster the indexing and be far more undertandable than [x*cols +y].

    Just to add, even though I said this before, that in C the index starts from 0, but in matlab it starts from 1. For just the for-loop is fine, but since you use the x,y in your matlab code, make sure that you get the desired results for x = 0 and y = 0. The same for the upper bounds that might be one less.

    In any case, you can pretend that the arrays start from 1 also in C and just ignore the very first element. That will guarantee that you won't have a bug by changing the index.
    You are right. In fact, I have just made a function to do the index:

    Code:
    int coord(int i, int j, int cols)
    {
    return (j-1) * cols + (i-1);
    }
    for (int x = 1; x < filas; x++){
        for(int y = 1; y < cols; y++){
          data2[coord(x,y,cols)] = ......
        }
    }
    And macro is a good idea, but might I define a macro to each array? Because I use 4 arrays.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Or, since it's a C++ function, you could make your data and data2 into an object, and make a function operator(int x, int y) which gives a reference to the relevant entry.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    And finally, there's Boost.MultiArray, which does exactly this.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to make a Packet sniffer/filter?
    By shown in forum C++ Programming
    Replies: 2
    Last Post: 02-22-2009, 09:51 PM
  2. "Cannot make pipe"
    By crepincdotcom in forum C Programming
    Replies: 5
    Last Post: 08-16-2004, 12:43 PM
  3. HELP!wanting to make full screen game windowed
    By rented in forum Game Programming
    Replies: 3
    Last Post: 06-11-2004, 04:19 AM
  4. make all rule
    By duffy in forum C Programming
    Replies: 9
    Last Post: 09-11-2003, 01:05 PM
  5. Replies: 6
    Last Post: 04-20-2002, 06:35 PM