C extract an array from a matrix using pointers - c

I wrote a code and I have some data stored in a 2d matrix:
double y[LENGTH][2];
I have a function that take as input a 1D array:
double function(double* data)
I am interested in passing the data stored in the first column of this matrix to this function. How can I do that using pointers?
My function is something like (where the array data is an array of double containing LENGTH elements:
double data[LENGTH];
):
double function(double* data){
double result=0;
for(int i=0; i<LENGTH; i++){
result+=data[i];
}
return result;
}
And I want to pass to this function a row of a matrix as data input.
Thanks to everyone in advance!

If you pass a pointer to the first element of your 2D matrix, you can access it as a 1 D matrix since the elements are stored contiguously:
double y[LENGTH][2];
x = function(y[0]);
...
double function(double* p) {
int ii;
double sum=0;
for(ii=0; ii<2*LENGTH; ii++) sum += p[ii];
return sum;
}
Note that in this case the order of accessing the elements is
y[0][0]
y[0][1]
y[1][0]
y[1][1]
y[2][0]
... etc
update - you just clarified your question a little bit. If you want to access just one column of data, you need to skip through the array. This means you need to know the size of the second dimension. I would recommend something like this:
double function(double* p, int D2) {
int ii;
double sum=0;
for(ii=0; ii<D2*LENGTH; ii+=D2) sum += p[ii];
return sum;
}
And you would call it with
x = function(y[colNum], numCols);
Now we start at a certain location, then, skip forward D2 elements to access the next element in the column.
I have to say that this is rather ugly - this is not really how C is intended to be used. I would recommend wrapping things into a class that handles these things for you cleanly - in other words, switch to C++ (although it's possible to write pure C functions that "hide" some of this complexity). You could of course copy the data to another memory block to make it contiguous, but that's usually considered a last recourse.
Be careful that you don't end up with code that is unreadable / unmaintainable...
further update
Per your comment, the above is still not what you wanted. Then I recommend the following:
double *colPointer(double *p, int rowCount, int colCount) {
double *cp;
int ii;
cp = malloc(rowCount * sizeof *cp);
for(ii=0; ii<rowCount; ii++) cp[ii] = *(p + ii * colCount);
return cp;
}
This will return a pointer to a newly created copy of the column. You call it with
double *cc;
cc = colPointer(y[colNum], LENGTH, 2);
answer = function(cc);
And now you can use cc in the way you wanted. If you have to do this many times you might be better off transposing the entire array just once - that way you can pass a pointer to a row of the transpose and achieve your result. You can adapt the code above to generate such a transpose.
Note that there is a risk of memory leaks if you don't clean up after yourself with this method.

the question is that do you consider to be the row-dimension.
usually the first one is rows and the second one cols.
that means that your double y[LENGTH][2]; is a matrix with LENGTH rows ans 2 cols.
if that is also your interpretation then the answer to your question is "you can't" since the memory is layed out like this:
r0c0 r0c1 r1c0 r1c1 r2c0 r2c1 ...
you can retrieve pointer to a row but not to a column.
matrix classes are usually designed in a way, that row and column step length is stored so that by carefully setting them you can build sub matrices on a big data chunk.
you may look for opencv matrix implementation if you plan to perform complexer tasks.
if you can change the implementation of the function you want to call. you can change it to accept the row step (number of your columns), so that it does not joust increment the pointer by one to reach the next element but to increment the pointer by row step.
as an alternative there is the obvious way to copy the required column to a new array.
edit:
fixed stupid error on memory layout diagram

Related

Pointer Math with Complex Array

I have this snippet of code with some pointer math that I'm having trouble understanding:
#include <stdlib.h>
#include <complex.h>
#include <fftw3.h>
int main(void)
{
int i, j, k;
int N, N2;
fftwf_complex *box;
fftwf_plan plan;
float *smoothed_box;
// Allocate memory for arrays (Ns are set elsewhere and properly,
// I've just left it out for clarity)
box = (fftwf_complex *)fftwf_malloc(N * sizeof(fftwf_complex));
smoothed_box = (float *)malloc(N2 * sizeof(float));
// Create complex data and fill box with it. Do FFT. Box has the
// Hermitian symmetry that complex data has when doing FFTs with
// real data
plan = fftwf_plan_dft_c2r_3d(N,N,N,box,(float *)box,
FFTW_ESTIMATE);
...
// end fft
// Now do the loop I don't understand
for(i = 0; i < N2; i++)
{
for(j = 0; j < N2; j++)
{
for(k = 0; k < N2; k++)
{
smoothed_box[R_INDEX(i,j,k)] = *((float *)box +
R_FFT_INDEX(i*f + 0.5, j*f + 0.5, k*f +0.5))/V;
}
}
}
// Do other stuff
...
return 0;
}
Where f and V are just some numbers that are set elsewhere in the code and don't matter for this particular question. Additionally, the functions R_FFT_INDEX and R_INDEX don't really matter, either. What's important is that, for the first loop iteration ,when i=j=k=0, R_INDEX = 0 and R_FFT_INDEX=45. smoothed_box has 8 elements and box has 320.
So, in gdb, when I print smoothed_box[0] after the loop, I get smoothed_box[0] = some number. Now, I understand that, for an array of normal types, say floats, array + integer will give array[integer], assuming that integer is within the bounds of the array.
However, fftwf_complex is defined as typedef float fftw_complex[2], as you need to hold both the real and imaginary parts of the complex number. It's also being casted to a float * from a fftwf_complex *, and I'm unsure what this does, given the typedef.
All I know is that when I print box[45] in gdb, I get box[45] = some complex number that is not smoothed_box[0] * V. Even when I print *((float *)box + 45)/V, I get a different number than smoothed_box[0].
So, I was just wondering if anyone could explain to me the pointer math that is being done in the above loop? Thank you, and I appreciate your time!
box is allocated as an array of N fftwf_complex. Then a backward 3D c2r fftw transform using N,N,N is performed on box, requiring N*N*(N/2+1) fftwf_complex. See http://www.fftw.org/fftw3_doc/Real_002ddata-DFT-Array-Format.html#Real_002ddata-DFT-Array-Format Therefore, this code might trigger undefined behavior, such as segmentation fault, before reaching the pointer arithmetics...
It is practical to cast back box to an array of float because the DFT is performed in place. Indeed, box is used twice as the fftwf_plan is created. box is both the input array of complex and the output array of real:
plan = fftwf_plan_dft_c2r_3d(N,N,N,box,(float *)box,
FFTW_ESTIMATE);
Once fftwf_execute(plan); is called, box is better seen as an array of real. Nevertheless, this array is of size N*N*2*(N/2+1), where the items located at positions i,j,k where k>N-1 are meaningless. See FFTW's Real-data DFT Array Format:
For an in-place transform, some complications arise since the complex data is slightly larger than the real data. In this case, the final dimension of the real data must be padded with extra values to accommodate the size of the complex data—two extra if the last dimension is even and one if it is odd. That is, the last dimension of the real data must physically contain 2 * (nd-1/2+1) double values (exactly enough to hold the complex data). This physical array size does not, however, change the logical array size—only nd-1 values are actually stored in the last dimension, and nd-1 is the last dimension passed to the planner.
This is the reason why the real array smoothed_box is introduced, though an N*N*N array would be expected. If smoothed_box were an array of size N*N*N, then the following conversion could have been performed:
for(i=0;i<N;i++){
for(j=0;j<N;j++){
for(k=0;k<N;k++){
smoothed_box[(i*N+j)*N+k]=((float *)box)[(i*N+j)*(2*(N/2+1))+k]
}
}
}

Efficiently sort a column of a two-dimensional array in C

I create a 2-dimensional Array in C via malloc like this:
double **x;
x = malloc(rows * sizeof(double*));
for (n = 0; n < rows; n++){
x[n] = malloc(columns * sizeof(double));
memset(x[n], 0, columns * sizeof(double));
}
I also check if malloc failed but for better readibility I posted that version. It actually works fine.
Now I have a function which is qsorting the elements row-wise:
double qsort_row_wise(double points[], int points_count)
Which I can call for a specific row(number 3 / 4th row) with 4+1 columns by:
my_qsort(x[3], 4);
This function is receiving a normal array and is also working well.
Now I want to use this function to qsort a column. That's why I am searching for something like this(which is not working):
my_qsort(x[][3], 4);
x[][3] here means a vector of all elements of the column 3.
If possible I would like to do a "vector"-like operation, not selecting everything step by step(for loop) for best performance.
Since you want a 2D array, it is better to allocate it as a single contiguous block:
double *x = calloc(rows * columns, sizeof(double)); // does zero init
Now you can index using arithmetic, so your my_qsort function should be declared like this:
void my_qsort(double *start, size_t count, size_t stride);
Now to sort row 3 you can do this:
my_qsort(x + 3 * columns, columns, 1);
And to sort column 5 you can do this:
my_qsort(x + 5, rows, columns);
During the sort, the elements you need to access are start[ii * stride], where ii goes from 0 to count. And start of course is simply the first cell in the 2D array that you wish to sort--typically either the leftmost cell in a row or the top cell in a column. It is also possible to use the same function to sort part of a row or column, or to sort an arbitrary "line" through the matrix, e.g. the diagonal of a square matrix:
my_qsort(x, rows, columns + 1);
Having a single allocation to store your 2D array not only makes "strided" operations easier, it is also more efficient, because it reduces the number of allocations, improves spatial locality, and on Linux, increases the chances that the memory will be instantly reclaimed when you free it, because "large" allocations are done via mmap rather than sbrk.
Well, you need to create an array the size of how many rows you have since a columns consists of n rows.
double *cols = malloc(nofrows * sizeof(double));
then loop through the 2 dimensional array over the rows and use the column index as a constant:
int whichcolumn = 1;
for (int i = 0; i < rows; i++)
cols[i] = x[i][whichcolumn];
then pass cols to the qsort function
qsort_row_wise(cols, nofrows);
If possible I would like to do a vector-operation, not selecting everything step by step(for loop) for best performance.
This is not possible.
What your 1st code snippet creates isn't a 2D-array, but one 1D-array of pointers, with each element pointing to a 1D-array of doubles. Such a construct sometimes is called a "scattered" array, as it consists of "number of rows"+1 not necessarily continuous blocks of memory.
Concluding from the latter fact, you cannot extract a column, as the elements are distributed throughout the memory and cannot be addressed by a single operation.

Best solution to represent Data[i,j] in c?

There is a pseudocode that I want to implement in C. But I am in doubt on how to implement a part of it. The psuedocode is:
for every pair of states qi, and qj, i<j, do
D[i,j] := 0
S[i,j] := notzero
end for
i and j, in qi and qj are subscripts.
how do I represent D[i,J] or S[i,j]. which data structure to use so that its simple and fast.
You can use something like
int length= 10;
int i =0, j= 0;
int res1[10][10] = {0, }; //index is based on "length" value
int res2[10][10] = {0, }; //index is based on "length" value
and then
for (i =0; i < length; i++)
{
for (j =0; j < length; j++)
{
res1[i][j] = 0;
res2[i][j] = 1;//notzero
}
}
Here D[i,j] and S[i,j] are represented by res1[10][10] and res2[10][10], respectively. These are called two-dimentional array.
I guess struct will be your friend here depending on what you actually want to work with.
Struct would be fine if, say, pair of states creates some kind of entity.
Otherwise You could use two-dimensional array.
After accept answer.
Depending on coding goals and platform, to get "simple and fast" using a pointer to pointer to a number may be faster then a 2-D array in C.
// 2-D array
double x[MAX_ROW][MAX_COL];
// Code computes the address in `x`, often involving a i*MAX_COL, if not in a loop.
// Slower when multiplication is expensive and random array access occurs.
x[i][j] = f();
// pointer to pointer of double
double **y = calloc(MAX_ROW, sizeof *y);
for (i=0; i<MAX_ROW; i++) y[i] = calloc(MAX_COL, sizeof *(y[i]));
// Code computes the address in `y` by a lookup of y[i]
y[i][j] = f();
Flexibility
The first data type is easy print(x), when the array size is fixed, but becomes challenging otherwise.
The 2nd data type is easy print(y, rows, columns), when the array size is variable and of course works well with fixed.
The 2nd data type also row swapping simply by swapping pointers.
So if code is using a fixed array size, use double x[MAX_ROW][MAX_COL], otherwise recommend double **y. YMMV

Delete a column from a double array

I'm stuck here. I've got a matrix of size NxN stored in a double array. Then I want to delete a given column, lets say the first column. So I created a new double array of size NxN-1 and copy the values from the first matrix to the second one, except the 1st column of course. But then I want to set the first array to be the second array. I am blanking here.
double matrix[N][N]
//fill up the matrix code here...
// remove first column of array
double newMatrix[N][N-1];
for(i = 0; i < N; i++){
for(j = 1; j < N; j++){
newMatrix[i][j-1] = matrix[i][j];
}
}
matrix = newMatrix; // how do I set this correctly? Do I need to realloc the first array?
You cannot assign arrays in C, which I assume that your compiler tells you. To do such dynamic memory management, you will need to use pointers instead of arrays. I suggest you read up on how malloc() and free() work so that you can do what you want.
Edit:
Another solution comes to mind if you are only removing columns (or rows): keep track of the number of rows and columns used in the array. Then you can remove a row or column within the original array without creating a copy first. Just move the data past the delete column (or row) to the left (or up) then decrement your size counters. (I hope this make sense. If not let me know and I'll elaborate.)
like Code-guru said malloc() and free() should help alot, but if u simply wanted to delete the last column the you wouldn't need two arrays:
double matrix[2][3] = {1,2,3,4,5,6}; //declaring a 2 by 3 matrix
for (i=0;i<2;i++) //rows
{
for (j=0;j<3-1;j++) //columns - 1
{
printf("%.1f ",matrix[i][j]); //I chose to display matrix...
}
printf("\n");
}
Instead of accessing elements from array[i][j], one might opt to access elements from array + stride_x[x] + stride_y[y]; where array is originally introduced as double matrix[N*N]; or double *matrix = malloc(sizeof(double)*N*N);.
The stride_y[x] would originally contain offsets of columns for all rows: 0 1 2 3 4 ... N-1 and stride_y[y] would contain similar offsets multiplied with original row width 0 N 2*N 3*N..
From these 1-D arrays one can more effortlessly delete or exchange complete rows and columns, which may come handy in eg. recursive implementation of determinant calculation / Gauss Jordan elimination.

Copying a subset of an array into another array / array slicing in C

In C, is there any built-in array slicing mechanism?
Like in Matlab for example,
A(1:4)
would produce =
1 1 1 1
How can I achieve this in C?
I tried looking, but the closest I could find is this: http://cboard.cprogramming.com/c-programming/95772-how-do-array-subsets.html
subsetArray = &bigArray[someIndex]
But this does not exactly return the sliced array, instead pointer to the first element of the sliced array...
Many thanks
Doing that in std C is not possible. You have to do it yourself.
If you have a string, you can use string.h library who takes care of that, but for integers there's no library that I know.
Besides that, after having what you have, the point from where you want to start your subset, is actually easy to implement.
Assuming you know the size of your 'main' array and that is an integer array, you can do this:
subset = malloc((arraySize-i)*sizeof(int)); //Where i is the place you want to start your subset.
for(j=i;j<arraySize;j++)
subset[j] = originalArray[j];
Hope this helps.
Thanks everyone for pointing out that there is no such built-in mechanism in C.
I tried using what #Afonso Tsukamoto suggested but I realized I needed a solution for multi-dimensional array. So I ended up writing my own function. I will put it in here in case anyone else is looking for similar answer:
void GetSlicedMultiArray4Col(int A[][4], int mrow, int mcol, int B[1][4], int sliced_mrow)
{
int row, col;
sliced_mrow = sliced_mrow - 1; //cause in C, index starts from 0
for(row=0; row < mrow; row++)
{
for (col=0; col < mcol; col++)
{
if (row==sliced_mrow) B[0][col]=A[row][col];
}
}
}
So A is my input (original array) and B is my output (the sliced array).
I call the function like this:
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
For example:
int A[][4] = {{1,2,3,4},{1,1,1,1},{3,3,3,3}};
int A_rows = 3;
int A_cols = 4;
int B[1][4]; //my subset
int target_row = 1;
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
This will produce a result (multidimensional array B[1][4]) that in Matlab is equal to the result of A(target_row,1:4).
I am new to C so please correct me if I'm wrong or if this code can be made better... thanks again :)
In C,as far as I know, array name is just regarded as a const pointer. So you never know the size of the subset. And also you can assign a arrary to a new address. So you can simply use a pointer instead. But you should manage the size of the subset yourself.

Resources