Rotate right by n only using bitwise operators in C - c

I'm trying to implement a rotateRight by n function in C by only using bitwise operators.
So far, I have settled on using this.
y = x >> n
z = x << (32 - n)
g = y | z
So take for instance the value 11010011
If I were to try and `rotateRight(5):
y becomes 11111110
z becomes 01100000
Then g becomes 111111110
However the correct answer should be 10011110
This almost works, but the problem is that the right-shift copies the sign bit when I need it to perform logical shift, and so some of my answers are the negative of what they should be. How can I fix this?
Note
I am unable to use casting or unsigned types

You could shift unsigned values:
y = (int)((unsigned)x >> n);
z = x << (32 - n);
g = y | z;
Or, you could mask appropriately:
y = (x >> n) & ~(-1 << (32 - n));
z = x << (32 - n);
g = y | z;

Though #jlahd answer is correct I will try and provide a brief explanation of the difference between a logical shift right and an arithmetic shift right (another nice diagram of the difference can be found here).
Please read the links first and then if you're still confused read below:
Brief explanation of the two different shifts right
Now, if you declare your variable as int x = 8; the C compiler knows that this number is signed and when you use a shift operator like this:
int x = 8;
int y = -8;
int shifted_x, shifted_y;
shifted_x = x >> 2; // After this operation shifted_x == 2
shifted_y = y >> 2; // After this operation shifted_y == -2
The reason for this is that a shift right represents a division by a power of 2.
Now, I'm lazy so lets make int's on my hypothetical machine 8 bits so I can save myself some writing. In binary 8 and -8 would look like this:
8 = 00001000
-8 = 11111000 ( invert and add 1 for complement 2 representation )
But in computing the binary number 11111000 is 248 in decimal. It can only represent -8 if we remember that that variable has a sign...
If we want to keep the nice property of a shift where the shift represents a division by a power of 2 (this is really useful) and we want to now have signed numbers, we need to make two different types of right shifts because
248 >> 1 = 124 = 01111100
-8 >> 1 = -4 = 11111100
// And for comparison
8 >> 1 = 4 = 00000100
We can see that the first shift inserted a 0 at the front while the second shift inserted a 1. This is because of the difference between the signed numbers and unsigned numbers, in two's complement representation, when dividing by a power of 2.
To keep this nicety we have two different right shift operators for signed and unsigned variables. In assembly you can explicitly state which you wish to use while in C the compiler decides for you based on the declared type.
Code generalisation
I would write the code a little differently in an attempt to keep myself at least a little platform agnostic.
#define ROTR(x,n) (((x) >> (n)) | ((x) << ((sizeof(x) * 8) - (n))))
#define ROTR(x,n) (((x) >> (n)) | ((x) << ((sizeof(x) * 8) - (n))))
This is a little better but you still have to remember to keep the variables unsigned when using this macro. I could try casting the macro like this:
#define ROTR(x,n) (((size_t)(x) >> (n)) | ((size_t)(x) << ((sizeof(x) * 8) - (n))))
#define ROTR(x,n) (((size_t)(x) >> (n)) | ((size_t)(x) << ((sizeof(x) * 8) - (n))))
but now I'm assuming that you're never going to try and rotate an integer larger than size_t...
In order to get rid of the upper bits of the right shift which may be 1's or 0's depending on the type of shift the compiler chooses one might try the following (which satisfies your no casting requirement):
#define ROTR(x,n) ((((x) >> (n)) & (~(0u) >> (n))) | ((x) << ((sizeof(x) * 8) - (n))))
#define ROTR(x,n) ((((x) >> (n)) & (~(0u) >> (n))) | ((x) << ((sizeof(x) * 8) - (n))))
But it would not work as expected for the long type since the ~(0u) is of type unsigned int (first type which zero fits in the table) and hence restricts us to rotations that are less than sizeof(unsigned int) * 8 bits. In which case we could use ~(0ul) but that makes it of unsigned long type and this type may be inefficient on your platform and what do we do if you want to pass in a long long? We would need it to be of the same type as x and we could achieve it by doing more magical expressions like ~((x)^(x)), but we would still need to turn it into and unsigned version so lets not go there.
#MattMcNabb also points out in the comments two more problems:
our left shift operation could overflow. When operating on signed types, even though in practice it is most often the same, we need to cast the x in the left shift operation to an unsigned type, because it is undefined behavior when an arithmetic shift operation overflows (see this answer's reference to the standard). But if we cast it we will once again need to pick a suitable type for the cast because its size in bytes will act as an upper limit on what we can rotate...
We are assuming that bytes have 8 bits. Which is not always the case, and we should use CHAR_BIT instead of 8.
In which case why bother? Why not go back to the previous solution and just use the largest integer type, uintmax_t (C99), instead of size_t. But this now means that we could be penalized in performance since we might be using integers larger than the processor word and that could involve more than just one assembly instruction per arithmetic operation... Nevertheless here it is:
#define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * CHAR_BIT) - (n))))
#define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * CHAR_BIT) - (n))))
So really, there is likely no perfect way to do it (at least none that I can think of). You can either have it work for all types or have it be fast by only dealing with things equal to or smaller than the processor word (eliminate long long and the likes). But this is nice and generic and should adhere to the standard...
If you want fast algorithms there is a point where you need to know what machine/s you're writing code for otherwise you can't optimize.
So in the end #jlahd's solution will work better, whilst my one might help you make things more generic (at a cost).

I've tried your code on x86 Linux with gcc 4.6.3.
y = x >> n
z = x << (32 - n)
g = y | z
This works correct.If x equals 11010011 then rotateRight(5) will makes y become 00000110.">>" will not add 1.

Related

Using only bit manipulations, return a mask that marks the position of the most significant 1 bit. If x == 0, return 0

As part of my coding class, an intro to C, I'm working on a coding project dealing with bit manipulation under restrictions. On this question in particular, I'm stuck because I don't know how to fix my error.
/*
* SigBitMask - return a mask that marks the position of the
* most significant 1 bit. If x == 0, return 0
* Example: SigBitMask(96) = 0x40
* Legal operations: ! ~ & ^ | + << >>
* Max operations: 16
* Rating: 4
*/
Besides the legal operations listed, I can't use any statements such as do, if, while, or else. I'm not allowed cast to other data types either., this includes using unsigned. Also I can't use any constant bigger than 0xFF, which is super important for this problem since I'm not allowed to use 0x80000000. Also, assume we are using a 32 bit machine.
A big thing here is that I can't use operations like - or * which would make this a lot easier.
Here is my code so far:
int SigBitMask(int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x = x ^ (x >> 1);
return x & ~(x >> 1);
}
The error the checking software is giving me says:
"ERROR: Test SigBitMask(-2147483648[0x80000000]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
I'm not quiet sure how to go about fixing my problem. I'd prefer more than just the answer. Can someone actually explain the process too. The whole point of this project is to learn to code in C. Thanks :)
Edit: I know there is a similar problem on Stack Overflow already, but their restrictions were different than mine, plus I'm looking for help fixing my code, and understanding why.
Edit2: Clarified what max and legal ops meant
Get rid of your last line because it doesn't do anything. So your function becomes:
int SigBitMask(int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x ^ (x >> 1);
}
This works great for non-negative inputs, but for negative inputs, x will be -1 when the last line runs, so the last line will give a result of zero. But that's bad, because we want to return -2147483648 (i.e. 0x80000000) for all negative inputs.
What if we could patch the return expression, by using | to combine it with another expression that is 0x80000000 when x is -1, and 0 when is x is non-negative? (We don't care about its values for other negative values of x.) Can you think of such an expression? I can think of one using only 3 operators, but it involves a little bit of undefined behavior.

Performance of bitwise operators in C

What is the fastest way to make the last 2 bits of a byte zero?
x = x >> 2 << 2;
OR
x &= 252;
Is there a better way?
Depends on many factors, including the compiler, the machine architecture (ie processor).
My experience is that
x &= 252; // or...
x &= ~3;
are more efficient (and faster) than
x = x >> 2 << 2;
If your compiler is smart enough, it might replace
x = x >> 2 << 2;
by
x &= ~3;
The later is faster than the former, because the later is only one machine instruction, while the former is two. And all bit manipulation instructions can be expected to execute in precisely one cycle.
Note:
The expression ~3 is the correct way to say: A bit mask with all bits set but the last two. For a one-byte type, this is equivalent to using 252 as you did, but ~3 will work for all types up to int. If you need to specify such a bitmask for a larger type like a long, add the appropriate suffix to the number, ~3l in the case of a long.

Moving a "nibble" to the left using C

I've been working on this puzzle for awhile. I'm trying to figure out how to rotate 4 bits in a number (x) around to the left (with wrapping) by n where 0 <= n <= 31.. The code will look like:
moveNib(int x, int n){
//... some code here
}
The trick is that I can only use these operators:
~ & ^ | + << >>
and of them only a combination of 25. I also can not use If statements, loops, function calls. And I may only use type int.
An example would be moveNib(0x87654321,1) = 0x76543218.
My attempt: I have figured out how to use a mask to store the the bits and all but I can't figure out how to move by an arbitrary number. Any help would be appreciated thank you!
How about:
uint32_t moveNib(uint32_t x, int n) { return x<<(n<<2) | x>>((8-n)<<2); }
It uses <<2 to convert from nibbles to bits, and then shifts the bits by that much. To handle wraparound, we OR by a copy of the number which has been shifted by the opposite amount in the opposite direciton. For example, with x=0x87654321 and n=1, the left part is shifted 4 bits to the left and becomes 0x76543210, and the right part is shifted 28 bits to the right and becomes 0x00000008, and when ORed together, the result is 0x76543218, as requested.
Edit: If - really isn't allowed, then this will get the same result (assuming an architecture with two's complement integers) without using it:
uint32_t moveNib(uint32_t x, int n) { return x<<(n<<2) | x>>((9+~n)<<2); }
Edit2: OK. Since you aren't allowed to use anything but int, how about this, then?
int moveNib(int x, int n) { return (x&0xffffffff)<<(n<<2) | (x&0xffffffff)>>((9+~n)<<2); }
The logic is the same as before, but we force the calculation to use unsigned integers by ANDing with 0xffffffff. All this assumes 32 bit integers, though. Is there anything else I have missed now?
Edit3: Here's one more version, which should be a bit more portable:
int moveNib(int x, int n) { return ((x|0u)<<((n&7)<<2) | (x|0u)>>((9+~(n&7))<<2))&0xffffffff; }
It caps n as suggested by chux, and uses |0u to convert to unsigned in order to avoid the sign bit duplication you get with signed integers. This works because (from the standard):
Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
Since int and 0u have the same rank, but 0u is unsigned, then the result is unsigned, even though ORing with 0 otherwise would be a null operation.
It then truncates the result to the range of a 32-bit int so that the function will still work if ints have more bits than this (though the rotation will still be performed on the lowest 32 bits in that case. A 64-bit version would replace 7 by 15, 9 by 17 and truncate using 0xffffffffffffffff).
This solution uses 12 operators (11 if you skip the truncation, 10 if you store n&7 in a variable).
To see what happens in detail here, let's go through it for the example you gave: x=0x87654321, n=1. x|0u results in a the unsigned number 0x87654321u. (n&7)<<2=4, so we will shift 4 bits to the left, while ((9+~(n&7))<<2=28, so we will shift 28 bits to the right. So putting this together, we will compute 0x87654321u<<4 | 0x87654321u >> 28. For 32-bit integers, this is 0x76543210|0x8=0x76543218. But for 64-bit integers it is 0x876543210|0x8=0x876543218, so in that case we need to truncate to 32 bits, which is what the final &0xffffffff does. If the integers are shorter than 32 bits, then this won't work, but your example in the question had 32 bits, so I assume the integer types are at least that long.
As a small side-note: If you allow one operator which is not on the list, the sizeof operator, then we can make a version that works with all the bits of a longer int automatically. Inspired by Aki, we get (using 16 operators (remember, sizeof is an operator in C)):
int moveNib(int x, int n) {
int nbit = (n&((sizeof(int)<<1)+~0u))<<2;
return (x|0u)<<nbit | (x|0u)>>((sizeof(int)<<3)+1u+~nbit);
}
Without the additional restrictions, the typical rotate_left operation (by 0 < n < 32) is trivial.
uint32_t X = (x << 4*n) | (x >> 4*(8-n));
Since we are talking about rotations, n < 0 is not a problem. Rotation right by 1 is the same as rotation left by 7 units. Ie. nn=n & 7; and we are through.
int nn = (n & 7) << 2; // Remove the multiplication
uint32_t X = (x << nn) | (x >> (32-nn));
When nn == 0, x would be shifted by 32, which is undefined. This can be replaced simply with x >> 0, i.e. no rotation at all. (x << 0) | (x >> 0) == x.
Replacing the subtraction with addition: a - b = a + (~b+1) and simplifying:
int nn = (n & 7) << 2;
int mm = (33 + ~nn) & 31;
uint32_t X = (x << nn) | (x >> mm); // when nn=0, also mm=0
Now the only problem is in shifting a signed int x right, which would duplicate the sign bit. That should be cured by a mask: (x << nn) - 1
int nn = (n & 7) << 2;
int mm = (33 + ~nn) & 31;
int result = (x << nn) | ((x >> mm) & ((1 << nn) + ~0));
At this point we have used just 12 of the allowed operations -- next we can start to dig into the problem of sizeof(int)...
int nn = (n & (sizeof(int)-1)) << 2; // etc.

C macro to create a bit mask -- possible? And have I found a GCC bug?

I am somewhat curious about creating a macro to generate a bit mask for a device register, up to 64bits. Such that BIT_MASK(31) produces 0xffffffff.
However, several C examples do not work as thought, as I get 0x7fffffff instead. It is as-if the compiler is assuming I want signed output, not unsigned. So I tried 32, and noticed that the value wraps back around to 0. This is because of C standards stating that if the shift value is greater than or equal to the number of bits in the operand to be shifted, then the result is undefined. That makes sense.
But, given the following program, bits2.c:
#include <stdio.h>
#define BIT_MASK(foo) ((unsigned int)(1 << foo) - 1)
int main()
{
unsigned int foo;
char *s = "32";
foo = atoi(s);
printf("%d %.8x\n", foo, BIT_MASK(foo));
foo = 32;
printf("%d %.8x\n", foo, BIT_MASK(foo));
return (0);
}
If I compile with gcc -O2 bits2.c -o bits2, and run it on a Linux/x86_64 machine, I get the following:
32 00000000
32 ffffffff
If I take the same code and compile it on a Linux/MIPS (big-endian) machine, I get this:
32 00000000
32 00000000
On the x86_64 machine, if I use gcc -O0 bits2.c -o bits2, then I get:
32 00000000
32 00000000
If I tweak BIT_MASK to ((unsigned int)(1UL << foo) - 1), then the output is 32 00000000 for both forms, regardless of gcc's optimization level.
So it appears that on x86_64, gcc is optimizing something incorrectly OR the undefined nature of left-shifting 32 bits on a 32-bit number is being determined by the hardware of each platform.
Given all of the above, is it possible to programatically create a C macro that creates a bit mask from either a single bit or a range of bits?
I.e.:
BIT_MASK(6) = 0x40
BIT_FIELD_MASK(8, 12) = 0x1f00
Assume BIT_MASK and BIT_FIELD_MASK operate from a 0-index (0-31). BIT_FIELD_MASK is to create a mask from a bit range, i.e., 8:12.
Here is a version of the macro which will work for arbitrary positive inputs. (Negative inputs still invoke undefined behavior...)
#include <limits.h>
/* A mask with x least-significant bits set, possibly 0 or >=32 */
#define BIT_MASK(x) \
(((x) >= sizeof(unsigned) * CHAR_BIT) ?
(unsigned) -1 : (1U << (x)) - 1)
Of course, this is a somewhat dangerous macro as it evaluates its argument twice. This is a good opportunity to use a static inline if you use GCC or target C99 in general.
static inline unsigned bit_mask(int x)
{
return (x >= sizeof(unsigned) * CHAR_BIT) ?
(unsigned) -1 : (1U << x) - 1;
}
As Mysticial noted, shifting more than 32 bits with a 32-bit integer results in implementation-defined undefined behavior. Here are three different implementations of shifting:
On x86, only examine the low 5 bits of the shift amount, so x << 32 == x.
On PowerPC, only examine the low 6 bits of the shift amount, so x << 32 == 0 but x << 64 == x.
On Cell SPUs, examine all bits, so x << y == 0 for all y >= 32.
However, compilers are free to do whatever they want if you shift a 32-bit operand 32 bits or more, and they are even free to behave inconsistently (or make demons fly out your nose).
Implementing BIT_FIELD_MASK:
This will set bit a through bit b (inclusive), as long as 0 <= a <= 31 and 0 <= b <= 31.
#define BIT_MASK(a, b) (((unsigned) -1 >> (31 - (b))) & ~((1U << (a)) - 1))
Shifting by more than or equal to the size of the integer type is undefined behavior.
So no, it's not a GCC bug.
In this case, the literal 1 is of type int which is 32-bits in both systems that you used. So shifting by 32 will invoke this undefined behavior.
In the first case, the compiler is not able to resolve the shift-amount to 32. So it likely just issues the normal shift-instruction. (which in x86 uses only the bottom 5-bits) So you get:
(unsigned int)(1 << 0) - 1
which is zero.
In the second case, GCC is able to resolve the shift-amount to 32. Since it is undefined behavior, it (apparently) just replaces the entire result with 0:
(unsigned int)(0) - 1
so you get ffffffff.
So this is a case of where GCC is using undefined behavior as an opportunity to optimize.
(Though personally, I'd prefer that it emits a warning instead.)
Related: Why does integer overflow on x86 with GCC cause an infinite loop?
Assuming you have a working mask for n bits, e.g.
// set the first n bits to 1, rest to 0
#define BITMASK1(n) ((1ULL << (n)) - 1ULL)
you can make a range bitmask by shifting again:
// set bits [k+1, n] to 1, rest to 0
#define BITNASK(n, k) ((BITMASK(n) >> k) << k)
The type of the result is unsigned long long int in any case.
As discussed, BITMASK1 is UB unless n is small. The general version requires a conditional and evaluates the argument twice:
#define BITMASK1(n) (((n) < sizeof(1ULL) * CHAR_BIT ? (1ULL << (n)) : 0) - 1ULL)
#define BIT_MASK(foo) ((~ 0ULL) >> (64-foo))
I'm a bit paranoid about this. I think this assumes that unsigned long long is exactly 64 bits. But it's a start and it works up to 64 bits.
Maybe this is correct:
define BIT_MASK(foo) ((~ 0ULL) >> (sizeof(0ULL)*8-foo))
A "traditional" formula (1ul<<n)-1 has different behavior on different compilers/processors for n=8*sizeof(1ul). Most commonly it overflows for n=32. Any added conditionals will evaluate n multiple times. Going 64-bits (1ull<<n)-1 is an option, but problem migrates to n=64.
My go-to formula is:
#define BIT_MASK(n) (~( ((~0ull) << ((n)-1)) << 1 ))
It does not overflow for n=64 and evaluates n only once.
As downside it will compile to 2 LSH instructions if n is a variable. Also n cannot be 0 (result will be compiler/processor-specific), but it is a rare possibility for all uses that I have(*) and can be dealt with by adding a guarding "if" statement only where necessary (and even better an "assert" to check both upper and lower boundaries).
(*) - usually data comes from a file or pipe, and size is in bytes. If size is zero, then there's no data, so code should do nothing anyway.
What about:
#define BIT_MASK(n) (~(((~0ULL) >> (n)) << (n)))
This works on all endianess system, doing -1 to invert all bits doesn't work on big-endian system.
Since you need to avoid shifting by as many bits as there are in the type (whether that's unsigned long or unsigned long long), you have to be more devious in the masking when dealing with the full width of the type. One way is to sneak up on it:
#define BIT_MASK(n) (((n) == CHAR_BIT * sizeof(unsigned long long)) ? \
((((1ULL << (n-1)) - 1) << 1) | 1) : \
((1ULL << (n )) - 1))
For a constant n such as 64, the compiler evaluates the expression and generates only the case that is used. For a runtime variable n, this fails just as badly as before if n is greater than the number of bits in unsigned long long (or is negative), but works OK without overflow for values of n in the range 0..(CHAR_BIT * sizeof(unsigned long long)).
Note that CHAR_BIT is defined in <limits.h>.
#iva2k's answer avoids branching and is correct when the length is 64 bits. Working on that, you can also do this:
#define BIT_MASK(length) ~(((unsigned long long) -2) << length - 1);
gcc would generate exactly the same code anyway, though.

Logical NOT (!) operator won't work with bitwise statement

I am attempting to determine if I can compute the sum of two 32 bit integers without overflow, while making use of only certain bitwise and other operators. So, if the integers x and y can be added without overflow, the following code should return 1, and 0 otherwise.
(((((x >> 31) + (y >> 31)) & 2) >> 1))
However, it returns 0 when it should be 1 and vice versa. When I employ the logical NOT (!) operator, or bitwise XOR (^) with 0x1, it does not fix the issue.
!(((((x >> 31) + (y >> 31)) & 2) >> 1))
(((((x >> 31) + (y >> 31)) & 2) >> 1) ^ 0x1)
^ these don't work.
Thanks in advance.
This is a bit cleaner:
~(x & y) >> 31
Update
kriss' comment is correct. all this code does is check that the two MSBs are both set.
I was just looking at kriss' answer, and it occurred to me that the same thing can be done using only a single addition, plus bitwise operators, assuming unsigned ints.
((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) & 0x80000000 & (x | y)
The first parenthesised section sets both MSB to 0 then adds the result. Any carry will end up in the MSB of the result. The next bitmask isolates that carry. The final term checks for a set MSB on either x or y, which result in a carry overall. To meet the spec in the question, just do:
~(((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) & 0x80000000 & (x | y)) >> 31
Let's suppose both numbers are unsigned integers. If you work with signed integers, it would be a little be more tricky as there is two ways to get overflow, either adding two large positives of adding two large negative. Anyway checking the most significant bits won't be enough, as addition propagates carry bit, you must take it into account.
For unsigned integers, if you don't care to cheat an easy way is:
(x+y < x) || (x+y < y)
This will work as most compilers won't do anything when overflow happen, just let it be.
You can also remarks that for overflow to happen at least one of the two numbers must have it's most significant bit set at 1. Hence something like that should work (beware, untested), but it's way more compilcated than the other version.
/* both Most Significant bits are 1 */
(x&y&0x80000000)
/* x MSb is 1 and carry propagate */
||((x&0x80000000)&&(((x&0x7FFFFFFF)+y)&0x80000000))
/* y MSb is 1 and carry propagate */
||((y&0x80000000)&&(((y&0x7FFFFFFF)+x)&0x80000000))
The logical ! is working fine for me.
me#desktop:~$ cat > so.c
#include <stdio.h>
void main() {
int y = 5;
int x = 3;
int t;
t = (((((x >> 31) + (y >> 31)) & 2) >> 1));
printf("%d\n", t);
t = !(((((x >> 31) + (y >> 31)) & 2) >> 1));
printf("%d\n", t);
}
^D
me#desktop:~$ gcc -o so so.c
me#desktop:~$ ./so
0
1
me#desktop:~$ uname -a
Linux desktop 2.6.32-23-generic #37-Ubuntu SMP Fri Jun 11 07:54:58 UTC 2010 i686 GNU/Linux
There is no simple bit-arithmetic-based test for overflow because addition involves carry. But there are simple tests for overflow that do not involve invoking overflow or unsigned integer wrapping, and they're even simpler than doing the addition then checking for overflow (which is of course undefined behavior for signed integers):
For unsigned integers x and y: (x<=UINT_MAX-y)
For signed integers, first check if they have opposite signs. If so, addition is automatically safe. If they're both positive, use (x<=INT_MAX-y). If they're both negative, use (x>=INT_MIN-y).
Are those signed integers by any chance? Your logic looks like it should be fine for unsigned integers (unsigned int) but not for regular ints, since in that case the shift will preserve the sign bit.

Resources