Ternary Operator in For Loop causing infinite iterations - c

I was working on a function to transpose an NxN matrix which is stored in an array of floats. My first implementation seemed to cause the function to loop infinitely and I can't seem to figure out why. Here is the original code:
for(int i = 0; i < numRows % 2 == 0 ? numRows / 2 : numRows / 2 + 1; i++)
{
for(int j = i + 1; j < numColumns; j++)
{
//Swap [i,j]th element with [j,i]th element
}
}
However the function never returns. Failing to see the error in my logic I rephrased the expression and now have the following working code:
int middleRow = numRows % 2 == 0 ? numRows / 2 : numRows / 2 + 1;
for(int i = 0; i < middleRow; i++)
{
for(int j = i + 1; j < numColumns; j++)
{
//Swap [i,j]th element with [j,i]th element
}
}
Can anybody help explain why the first version does not work but the seemingly equivalent second version does?

As per the operator precedence table, < has higher priority over ?:. You need to use () as required explicitly to enforce the required priority.
Change
for(int i = 0; i < numRows % 2 == 0 ? numRows / 2 : numRows / 2 + 1; i++)
to
for(int i = 0; i < ( numRows % 2 == 0 ? numRows / 2 : numRows / 2 + 1) ; i++)
Note: Please use the second approach. Much, Much better in readability, maintenance and understanding.

I think there is a problem with the precedence of the operators.
If you want to keep the cluttered first version (which I don't recommend) use parenthesis:
i < (numRows % 2 == 0 ? numRows / 2 : numRows / 2 + 1)

Try:
i < ((numRows + 1) / 2)
If numRows is even, it will just be numRows/2. If odd, it will be numRows/2+1.
That will be faster and avoids branching due to the compare (unless you have a n excelent compiler which knows this pattern - unlikely.
You sometimes have to step back to see the whole picture.

Related

Nested loops for creating a spiral shape pattern in c

I need to make a spiral pattern made of stars '*' using nested for loops. I managed to make outter lines, now I don't know how to repeat smaller swirls in the same place.
What I should have:
*********
*
******* *
* * *
* *** * *
* * * *
* ***** *
* *
*********
Any help would be greatly appreciated.
After being thoroughly nerd-sniped, I came up with this:
#include <stdio.h>
void print_spiral(int size)
{
for (int y = 0; y < size; ++y)
{
for (int x = 0; x < size; ++x)
{
// reflect (x, y) to the top left quadrant as (a, b)
int a = x;
int b = y;
if (a >= size / 2) a = size - a - 1;
if (b >= size / 2) b = size - b - 1;
// calculate distance from center ring
int u = abs(a - size / 2);
int v = abs(b - size / 2);
int d = u > v ? u : v;
int L = size / 2;
if (size % 4 == 0) L--;
// fix the top-left-to-bottom-right diagonal
if (y == x + 1 && y <= L) d++;
printf((d + size / 2) % 2 == 0 ? "X" : " ");
}
printf("\n");
}
}
As others mentioned, it might be more intuitive to allocate an array representing the grid, and draw the spiral into the array (within which you can move freely), then print the array. But, this solution uses O(1) memory.
It could almost certainly be optimized and simplified a bit, but I'll "leave that as an exercise for the reader" as I've already spent too much time on this ;-)
Update
I'm not going to spend any more time on this, but I had an idea for a second attempt that might result in simpler code. If you check the output at increasingly large sizes, a pattern emerges:
Within each quadrant, the pattern is regular and can be easily coded. I think you would just have to carefully classify the (x, y) coordinates into one of the four quadrants and then apply the appropriate pattern.
The most sensible approach is to create a 2d array, then fill it with the * that you want.
Alternatively, you can try to come up with some "just in time" logic to avoid a buffer. This is more complicated.
I came up with an approach by thinking of the spiral as four different triangles that form a square. Here I have printed "a,b,c,d" for each of the four triangles to show what I mean:
aaaaaaaaaac
c
baaaaaac c
b c c
b baac c c
b b dd c c
b b c c
b dddddd c
b c
dddddddddd
There are two tricky parts to this. One is to align the diagonals correctly. Not so hard with with trial and error. The other tricky party is that not all squares divide into alternating lines the same way. You can see in the example above a square n=11, the left side is shifted by one. Perhaps there is a better solution, but this attempts to create alternating rows and columns.
n = 11;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
// top
if (j > i - 2 && j < n - i && i % 2 == (n&1)) printf("a");
// left
else if (j < i - 1 && j < n - i && j % 2 == (n & 1)) printf("b");
// right
else if (j > n - i -1&& j > i && j % 2 == ((n+1) & 1)) printf("c");
// bottom
else if (j < i + 1 && j > n - i - 1 && i % 2 == ((n + 1) & 1)) printf("d");
else printf(" ");
}
printf("\n");
}
I would recommend taking a look at the NCurses library. It contains many methods for moving the cursor in the terminal window, such as mvaddch() and curs_set().
Here is a document that contains everything you'd need to know on how to use NCurses.
However, if you don't want to use external libraries, then you could define a 2D array of ints or bools and then print a * where an index is 1 or true, respectively.
Example of the latter:
#include <stdbool.h> //You need to include this header file if you want to use 'bool's
...
//Using a 10x10 array for this example
bool stars[10][10] = { /* initialize the 2D array here */ };
...
//Get the length of a row
int rowLength = (sizeof stars[0]) / (sizeof stars[0][0]);
//Get the amount of rows
int rowAmount = (sizeof stars) / (sizeof stars[0]));
//Print the spiral using the array "stars"
for(int r = 0; r < rowAmount; r++){
for(int c = 0; c < rowLength; c++){
if(stars[r][c])
printf("*");
else
printf(" ");
}
printf("\n");
}
...

Break or merge loops over arrays in C?

Let's say I have 3 arrays image, blur and out, all of dimensions M×N×3.
I want to compute the bilateral gradient of each pixel in the array image (current_pixel - (previous_previous + next_pixel) / 2) over x and y dimensions, divide it by some floats, then add the value of the corresponding pixel from the array blur and finally put the result into the array out.
My question is, in C, what is the most efficient way to do it (regarding the memory access speed and computing efficiency) :
One loop indexing the 3 arrays at once :
for (i = 0, j = 0, k = 0 ; i < M-1, j < N-1, k < 3 ; i++, j++, k++):
out[i][j][k] = (2 * image[i][j][k] - image[i+1][j][k] - image[i][j+1][k]) / 2. + lambda * blur[i][j][k]
Two loops indexing only two arrays :
for (i = 0, j = 0, k = 0 ; i < M-1, j < N-1, k < 3 ; i++, j++, k++):
out[i][j][k] = (2 * image[i][j][k] - image[i+1][j][k] - image[i][j+1][k]) / 2.
for (i = 0, j = 0, k = 0 ; i < M-1, j < N-1, k < 3 ; i++, j++, k++):
out[i][j][k] += lambda * blur[i][j][k]
(for readability, I only wrote a simple forward gradient, but the complete formula is given above).
Or is there another faster way ? I'm programming for x86_64 CPUs.
One loop indexing the 3 arrays at once will be slightly easier for compiler to optimize. But you can quite likely check it and tested it.

How to set a random matrix in this case?

Recently I saw link on this site
Sweeping through a 2d arrays using pointers with boundary conditions
Here, in "answers", is a code of boundary conditions in Ising Model.
This code generate a matrix with all spins up:
for (i=0; i<Lattice_Size; i++) {
for (j=0; j<Lattice_Size; j++) {
*ptr++ = spin_up; // initializing to parallel spins,
// where spin_up is an integer number
// taking value = +1.
}
}
My question is: How one can set up a random configuration (matrix) with random distribution of spin_up / spin_down spins?
I thought it might be done with the help of function random(...), but I figured out that I don't understand well how it works :(
You could use the function rand modulo 2:
srand(time(NULL)) ; // Initialize the rand see
for (i=0; i < Lattice_Size; i++) {
for (j=0; j < Lattice_Size; j++) {
*ptr++ = 1 - 2 * (rand() % 2); // Return either 1 or - 1
}
}
Don't forget to include time.h and stdlib.h.
rand() returns a number in the range between 0 and RAND_MAX
rand() % 2 returns either 0 or 1
2 * (rand() % 2) returns either 0 or 2
1 - 2 * (rand() % 2) returns -1 or 1.
If you are not familiar with it, % is the modulo operator.

I am writing a max filter. This replaces each pixel RGB channel with the maximum channel intensity of the surrounding 9 pixels

Here is the code I am using. When I run it, it doesn't seem to change anything in the image except the last 1/4 of it. That part turns to a solid color.
void maxFilter(pixel * data, int w, int h)
{
GLubyte tempRed;
GLubyte tempGreen;
GLubyte tempBlue;
int i;
int j;
int k;
int pnum = 0;
int pnumWrite = 0;
for(i = 0 ; i < (h - 2); i+=3) {
for(j = 0 ; j < (w - 2); j+=3) {
tempRed = 0;
tempGreen = 0;
tempBlue = 0;
for (k = 0 ; k < 3 ; k++){
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
if ((data[pnum].g) > tempGreen){tempGreen = (data[pnum + k].g);}
if ((data[pnum].b) > tempBlue){tempBlue = (data[pnum + k].b);}
if ((data[(pnum + w)].r) > tempRed){tempRed = (data[(pnum + w)].r);}
if ((data[(pnum + w)].g) > tempGreen){tempGreen = (data[(pnum + w)].g);}
if ((data[(pnum + w)].b) > tempBlue){tempBlue = (data[(pnum + w)].b);}
if ((data[(pnum + 2 * w)].r) > tempRed){tempRed = (data[(pnum + 2 * w)].r);}
if ((data[(pnum + 2 * w)].g) > tempGreen){tempGreen = (data[(pnum + 2 * w)].g);}
if ((data[(pnum + 2 * w)].b) > tempBlue){tempBlue = (data[(pnum + 2 * w)].b);}
pnum++;
}
pnumWrite = pnum - 3;
for (k = 0 ; k < 3 ; k++){
((data[pnumWrite].r) = tempRed);
((data[pnumWrite].g) = tempGreen);
((data[pnumWrite].b) = tempBlue);
((data[(pnumWrite + w)].r) = tempRed);
((data[(pnumWrite + w)].g) = tempGreen);
((data[(pnumWrite + w)].b) = tempBlue);
((data[(pnumWrite + 2 * w)].r) = tempRed);
((data[(pnumWrite + 2 * w)].g) = tempGreen);
((data[(pnumWrite + 2 * w)].b) = tempBlue);
pnumWrite++;
}
}
}
}
I can see several problems with that code - being difficult to follow not being the least!
I think your main problem is that the loop is (as you probably intended) run through h/3 * w/3 times, once for each 3x3 block in the image. But the pnum index runs only increases by 3 for each block, and reaches a maximum of about h*w/3, rather than the intended h*w. That means that only the first third of your image will be affected by your filter. (And I suspect your painting is done 'bottom-up', so that's why you see the lowest part change. I remember .bmp files being structured that way, but perhaps there are others as well.)
The 'cheap' fix would be to add 2*w at the right point, but nobody will ever understand that code again. I suggest you rewrite your indexing instead, and explicitly compute pnum from i and j in each turn through the loop. That can be improved on for readability, but is reasonably clear.
There's another minor thing: you have code like
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
where the indexing on the right and on the left differ: this is probably also giving you results different from what you intended.
As Jongware points out, writing to the input array is always dangerous - your code is intended, I believe, to avoid that problem by only looking once into each 3x3 block, but his suggestion of a separate output array is very sensible - you probably don't want the blockiness your code gives anyway (you make each 3x3 block all one colour, don't you?), and his suggestion would let you avoid that.

Generating a Sparse Matrix in C

Is there a simpler way of generating sparse matrix other than this?
for (i = 0; i < 1000; i++)
{
if (rand() % 3 == 0)
{
array[i] = rand() % 3;
}
else
{
array[i] = ((rand() % 3) - 1);
}
}
Thanks.
I used array for presentational purposes
With a determine how sparse you want it to be.
for (i = 0; i < 1000; i++)
{
if (rand() % a == 0)
{
array[i] = rand() % 100;
}
else
{
array[i] = 0;
}
}
Let t be the target number of non-zero elements in the array, which should be much less than the length of the array for sparseness. I'm assuming your array is of length length. I'm also generating the random indices without the modulus operator to avoid modulo bias.
for (i = 0; i < t; ++i) {
int index = (int) (length * ((double) rand() / (RAND_MAX + 1.0)));
array[index] = i % 2 ? -1 : 1;
}
Note that this may give a few less than t non-zero elements because random numbers can produce duplicates, but that should be rare if it really is sparse, e.g., t < square root of the array length. If you're worried about duplicate randoms making things sparser than you want, you can modify accordingly:
for (i = 0; i < t;) {
int index = (int) (length * ((double) rand() / (RAND_MAX + 1.0)));
if (array[index]) { /* something already at this index */
continue; /* skip incrementing and try again */
}
array[index] = i % 2 ? -1 : 1;
++i;
}
In both cases I'm alternating +/- ones for the non-zero values, but if you want it more random that would be easy to replace the right-hand side of the assignment of array[index].
Finally, I ask your indulgence if I fluffed something on C syntax. My C is about 15 years rusty, but the intent should be clear.

Resources