what does "|=" operator mean in C? - c

How does this code work:
int a = 1;
int b = 10;
a |= b;
how the a |= b; works? Seems like |= is not an operator in C?

It works like the | + the = operator, in a similar way as += works.
It is equivalent as
a = a|b;
I suggest you to read this article about operators: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Bitwise_operators
Ans this one about bitwise operation
http://en.wikipedia.org/wiki/Bitwise_operation

Following the pattern of, for example, +=:
a |= b;
// Means the same thing as:
a = a | b;
That is, any bits that are set in either a or b shall be set in a, and those set in neither shall not be set in a.

That's the "bitwise or" equal. It follows in the pattern of the plus equal +=, minus equal -=, etc.
a |= b; is the same as a = a | b;

The expression a |= b; is equivalent to the expression a = a | b;.

This is compound assignment operator.
It has meaning:
a = a | b;

This is the same as
a = a | b;
The same way as += -= etc

Its the bitwise OR operator, and
a |= b;
Its the same thing as
a = a | b;

Related

Trying to confirm XOR's mathematical property

Is the following property true of the XOR operator ?
A XOR B = C
A XOR C = B
B XOR C = A
What would you call this property ?
This can be tested here. Let me know if there are any cases where this property
doesn't hold true :
int main() {
unsigned a = 128;
unsigned b = 34;
unsigned c = a ^ b;
printf("a ^ c = %u\n", a ^ c); // Gives you b (34)
printf("b ^ c = %u\n", b ^ c); // Gives you a (128)
}
Involution
"The XOR bitwise operation with a given value for one parameter is an involution."
I don't think so, the above can be written as
A XOR A XOR B
Here A XOR A is 0
So the result is 0 XOR C = C
I don't think there is a name for such property. It implies from other properties of the Exclusive Or (see Exclusive Or wiki for more details).
Here is the proof:
If a^b = c, then
a^c = a^(a^b) =
<by associativity>
= (a^a)^b =
= 0^b = b

Is there a way to manipulate the bits that I shift in C

If I have an int a, which is lets say equal to 0.
Is there a way for me to say left shift 101 into the variable and then in another step shift in 011 into it? Then I could get the int decimal number at the end? It would end up becoming 0b00000000000000000000000000101011.Or should I only use the OR operation.
You can't shift bits into the variable; you can OR them in:
int a = 0;
a |= 5;
printf("a = %d\n", a);
a <<= 3;
a |= 3;
printf("a = %d\n", a);
If your system supports binary constants, you can use those instead of decimals (and you can prefix 5 and 3 with 0 for octal or 0x for hexadecimal if you prefer — and you can print with a different format according to taste, too). If the starting value for a isn't known to be 0, you would do a shift-assignment operation before the first |= operation.
Eventually, you have to worry about left-shifting a signed integer value such that overflow occurs — that leads to undefined behaviour. It isn't a problem with the values in the question, though.
You would need to first shift by the required number of bits then perform a bitwise OR of the new data.
int a = 0;
a = a << 3;
a = a | 0x5;
a = a << 3;
a = a | 0x3;
printf("a=%x\n", a);
( Used separate assignments and operators instead of compound operators to make it clearer to beginners. )
Result:
a=2b
Is there a way for me to say left shift 101 into the variable
No. You need to left shift first, then add (or OR) the new value.
int eax = 0;
eax <<= 3;
eax |= 5;
int a = 0;
a << 3;
a |= 0x5;
a << 3;
a |= 0x3;
There isn't a predefined way to "shift in" a value like that. It wouldn't take much time to write a function that could though.
There is - to my knowledge - no operation that "shifts" a number of bits from one integer into another. The left shift operator always fills the arising spaces with 0, such that you have to combine it with, for example, an |-operation (actually a + would have the same effect in your case).
#include <stdio.h>
void printBinary(int b, int nrOfBits) {
for (int mask = (1 << nrOfBits); mask != 0; mask >>=1 ) {
char c = (b & mask) ? '1' : '0';
printf("%c", c);
}
}
int main()
{
int a = 0;
a = (a << 3) | 0x5;
printBinary(a, 8);printf("\n");
a = (a << 3) | 0x3;
printBinary(a, 8);printf("\n");
return 0;
}
When using left shift operators on signed datatypes be careful not to produce undefined behaviour (cf. cppreference concerting arithmetic operations):
When signed integer arithmetic operation overflows (the result does
not fit in the result type), the behavior is undefined

Multiply-subtract in SSE

I am vectorizing a piece of code and at some point I have the following setup:
register m128 a = { 99,99,99,99,99,99,99,99 }
register m128 b = { 100,50,119,30,99,40,50,20 }
I am currently packing shorts in these registers, which is why I have 8 values per register. What I would like to do is subtract the i'th element in b with the corresponding value in a if the i'th value of b is greater than or equal to the value in a (In this case, a is filled with the constant 99 ). To this end, I first use a greater than or equal to operation between b and a, which yields, for this example:
register m128 c = { 1,0,1,0,1,0,0,0 }
To complete the operation, I'd like to use the multiply-and-subtract, i.e. to store in b the operation b -= a*c. The result would then be:
b = { 1,50,20,30,0,40,50,20 }
Is there any operation that does such thing? What I found were fused operations for Haswell, but I am currently working on Sandy-Bridge. Also, if someone has a better idea to do this, please let me know (e.g. I could do a logical subtract: if 1 in c then I subtract, nothing otherwise.
You essentially want an SSE version of this code, right?
if (b >= a)
t = b-a
else
t = b
b = t
Since we want to avoid conditionals for the the SSE version so we can get rid of the control flow like this (note that the mask is inverted):
uint16_t mask = (b>=a)-1
uint16_t tmp = b-a;
uint16_t d = (b & mask) | (tmp & ~mask)
b = d
I've checked the _mm_cmpgt_epi16 intrinsic and it has a nice property in that it returns either 0x0000 for false or 0xFFFF for true, instead of a single bit 0 or 1 (thereby eliminating the need for the first subtraction). Therefore our SSE version might look like this.
__m128i mask = _mm_cmpgt_epi16 (b, a)
__m128i tmp = _mm_sub_epi16 (b, a)
__m128 d = _mm_or_ps (_mm_and_ps (mask, tmp), _mm_andnot_ps (mask, b))
EDIT: harold has mentioned a far less complicated answer. The above solution might be helpful if you need to modify the else part of the if/else.
uint16_t mask = ~( (b>=a)-1 )
uint16_t tmp = a & mask
b = b - tmp
the SSE code will be
__m128i mask = _mm_cmpgt_epi16 (b, a)
__m128i t = _mm_sub_epi16 (b, _mm_and_si128 (mask, a))
Another alternative, if your inputs are unsigned, you can calculate
b = min(b, b-a);
This works, because if a>b then b-a wraps around and is guaranteed to result in a bigger value than b. For a<=b you will always get a value between 0 and b inclusive.
b = _mm_min_epu16(b, _mm_sub_epi16(b,a));
The required _mm_min_epu16 requires SSE4.1 or later (_mm_min_epu8 would require only SSE2).
You can copy b to c, subtract a from c, perform an arithmetic shift right by 15 positions in the 16 bit values, complement the value of c, mask c with a, and finally subtract c from b.
I'm not familiar for the intrinsics syntax, but the steps are:
register m128 c = b;
c -= a;
c >>= 15;
c = ~c;
c &= a;
b -= c;
here is an alternative with fewer steps:
register m128 c = compare_ge(b, a);
c = -c;
c &= a;
b -= c;

C - Logical Compound Operators

Is the compound operator '&=' logical or bitwise AND ?
In other words, is a &= b the same as:
a = a & b
a = a && b
a &= b is using the bitwise AND operator. Think of the += operation:
a += 5;
is the same as:
a = a + 5;
It's just a combination of two operations: & and =.
It's the bitwise AND, not the logical. (have to add some characters)
In C, a &= b is a = a & b, i.e. bitwise. In C++, where there is a dedicated bool type, &= on booleans is boolean as well, as is a simple & on bool. None of these does exhibit the short-circuit behaviour of &&, though.
It's bitwise ANDsimple
When you do a&=b It means a=a&b
Remember aand bshould be integral typeor promoted to integer type
While && is logical AND.
This is one of the queries that can be resolved through experimentation rather than interrogation:
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char *argv[]) {
uint8_t a = 0xFF;
uint8_t b = 0x0F;
a &= b;
printf("a &= b : %02X\n",a);
a = 0xFF;
printf("a & b : %02X\n", a & b);
printf("a && b: %02X\n", a && b);
}
Prints:
a &= b : 0F
a & b : 0F
a && b: 01
to the console.

Bit Operators: Difference between << and <<= or >> and >>= in c

Please explain to me in detail the difference between << and <<= and as well as >> and >>=.
I know how shift operators work, but I am not so sure about them when it comes to >>= or <<=.
Well << only shifts left. <<= shifts left and assigns.
<<= is to << what += is to +.
EDIT
As suggested by MByD, here is an example
int x = 1;
/* Print 32. */
printf("%d\n", x << 5);
/* x stays the same. */
printf("%d\n", x);
x <<= 5;
/* x has become 32. */
printf("%d\n", x);
In C, and many other languages, you can put = after an operator as a shortcut. Instead of writing...
x = x + 5
...I can write...
x += 5
These are called compound assignment operators. You're just seeing the versions of these for bit shift operations.
x >>= 1
...is the same as...
x = x >> 1
<< can be used on both variables and constants.
5 << 2; // this is ok.
a << 2; // this is ok too.
<<= will change the lvalue, so that:
a <<= 2; // bit-shifts a by two positions.
5 <<= 2; // wrong, 5 is 5 and will always be 5.

Resources