Rotate array problem

Thread Starter

Art

Joined Sep 10, 2007
806
Hi Guys,
This is a function that can rotate a 256 element array:

int ii, jj;

for (ii = 1; ii <=1; ii++) {
for (jj = 256-1; jj > 0; jj--) {
colours[jj-1] = colours[jj-1] + colours[jj];
colours[jj] = colours[jj-1] - colours[jj];
colours[jj-1] = colours[jj-1] - colours[jj];
}}
Problem is it rotates in the wrong direction.
Anyone want to have a crack at the other direction?
No matter what I try I break it.

I realise I can just replace the 1 for 255 and use this for the same effect
as the other direction, but that takes too much time for the application.
Cheers, Art.
 

THE_RB

Joined Feb 11, 2008
5,438
Here are 2 simple systems, they circular rotate the data either way. The rotation has been kept as simple as possible and the last array element
is manually held in dat and restored at the end. There's plenty of other
ways to do it, but these are basically a mirror image of each other so
you might find them easy to understand.

Rich (BB code):
// rotates array data right (up)
unsigned char i;
unsigned char dat;

i=0;
dat = colours[0];
while(--i)
{
	colours[i+1] = colours;
}
colours[1] = dat;


// rotates array data left (down)
unsigned char i;
unsigned char dat;

i=0;
dat = colours[1];
while(++i)
{
	colours = colours[i+1];
}
colours[0] = dat;
 
Last edited:

RiJoRI

Joined Aug 15, 2007
536
Some compilers will not do this as desired:
Rich (BB code):
i=0;
while(i--)
They will (should? ) test i before decrementing it -- which is, after all, what you are telling it to do. The code also assumes a char is an 8-bit value.

A better way would be
Rich (BB code):
for(i = 0; i < 256; i++)
This way it is quite plain what you are trying to do.

And don't forget, marketing is going to want to change the colour array to 300 entries in a few years. Searching for all occurrences of 256 is going to be A Real Pain.

--Rich
(Burnt by C)
 

Mark44

Joined Nov 26, 2007
628
Neither Rich nor THE_RB mentioned this, but your outer loop executes only once. Surely you didn't intend that. Here is your code, unchanged except that I formatted it for better readability.
Rich (BB code):
int ii, jj;

for (ii = 1; ii <=1; ii++) 
{
    for (jj = 256-1; jj > 0; jj--) 
    {
        colours[jj-1] = colours[jj-1] + colours[jj];
        colours[jj] = colours[jj-1] - colours[jj];
        colours[jj-1] = colours[jj-1] - colours[jj];
    }
}
 

Thread Starter

Art

Joined Sep 10, 2007
806
Thanks for the replies :)
but your outer loop executes only once. Surely you didn't intend that.
Yeah, the constant 1 can be a variable that determines how many places to shift.
 

THE_RB

Joined Feb 11, 2008
5,438
Some compilers will not do this as desired:
Rich (BB code):
i=0;
while(i--)
They will (should? ) test i before decrementing it -- which is, after all, what you are telling it to do. The code also assumes a char is an 8-bit value.
A good point, but I believe you are wrong. In C the compiler will perform the expression first, before evaluating it. That is if the compiler conforms to C rules which it should.

A better way would be
Rich (BB code):
for(i = 0; i < 256; i++)
This way it is quite plain what you are trying to do.

And don't forget, marketing is going to want to change the colour array to 300 entries in a few years. Searching for all occurrences of 256 is going to be A Real Pain.

--Rich
(Burnt by C)
Yeah I hear you there, a for() expression is the standard way to do it. But the while() expression compiles to a lot smaller and faster code, something i've been made very aware of lately since my C coding these days is mainly for low level PIC micros where every uS counts.

When the original poster mentioned "takes too much time for the application" I assumed execution time was critical and stripped the code to the very fastest and minimal code I could think up in 2 minutes. ;)
 

RiJoRI

Joined Aug 15, 2007
536
... In C the compiler will perform the expression first, before evaluating it. That is if the compiler conforms to C rules which it should.
From: http://docs.hp.com/en/B3901-90007/ch05s09.html

lvalue++ Increments the current value of lvalue after lvalue has been referenced.

lvalue-- Decrements the current value of lvalue after lvalue has been referenced.

++lvalue Increments the current value of lvalue before lvalue is referenced.

--lvalue Decrements the current value of lvalue before lvalue has been referenced.
As to the for/while question, I usually check the output of the compiler to see which, if either, is faster. A possible reason for sluggishness is the arithmetic contortions the OP is going through in the loop. I'd look to see if using pointers was better, or maybe strcpy().

--Rich
 

Mark44

Joined Nov 26, 2007
628
In C the compiler will perform the expression first, before evaluating it.
Rich is right on the mark here. Not to pile on here, but for the post-decrement expression i--, the compiler generates code that evaluates the expression (an expression doesn't get performed), and after that decrements the variable.
 

THE_RB

Joined Feb 11, 2008
5,438
Whoops my apologies Rich, you are right I should have typed;

while(--i)
and
while(++i)
(I fixed it now with an edit)

I do understand pre and post incrementing but that typo slipped past me, which was why I was defending the fact that it performs the ++i increment expression first before being evaluated by the while() expression.

Nice link Sgtwookie. Still the best way to handle a circular array is still to leave the data where it is and reference it by a pointer. How often do you actually NEED to rotate the data in a circular array?
 
Top