what this "if(k.c[3] & c)" part of code doing? - c++

#include<stdio.h>
#include<iostream.h>
main()
{
unsigned char c,i;
union temp
{
float f;
char c[4];
} k;
cin>>k.f;
c=128;
for(i=0;i<8;i++)
{
if(k.c[3] & c) cout<<'1';
else cout<<'0';
c=c>>1;
}
c=128;
cout<<'\n';
for(i=0;i<8;i++)
{
if(k.c[2] & c) cout<<'1';
else cout<<'0';
c=c>>1;
}
return 0;
}

if(k.c[2] & c)
That is called bitwise AND.
Illustration of bitwise AND
//illustration : mathematics of bitwise AND
a = 10110101 (binary representation)
b = 10011010 (binary representation)
c = a & b
= 10110101 & 10011010
= 10010000 (binary representation)
= 128 + 16 (decimal)
= 144 (decimal)
Bitwise AND uses this truth table:
X | Y | R = X & Y
---------
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1
See these tutorials on bitwise AND:
Bitwise Operators in C and C++: A Tutorial
Bitwise AND operator &

A bitwise operation (AND in this case) perform a bit by bit operation between the 2 operands.
For example the & :
11010010 &
11000110 =
11000010

Bitwise Operation in your code
c = 128 therefore the binary representation is
c = 10000000
a & c will and every ith but if c with evert ith bit of a. Because c only has 1 in the MSB position (pos 7), so a & c will be non-zero if a has a 1 in its position 7 bit, if a has a 0 in pos bit, then a & c will be zero. This logic is used in the if block above. The if block is entered depending upon if the MSB (position 7 bit) of the byte is 1 or not.
Suppose a = ? ? ? ? ? ? ? ? where a ? is either 0 or 1
Then
a = ? ? ? ? ? ? ? ?
AND & & & & & & & &
c = 1 0 0 0 0 0 0 0
---------------
? 0 0 0 0 0 0 0
As 0 & ? = 0. So if the bit position 7 is 0 then answer is 0 is bit position 7 is 1 then answer is 1.
In each iteration c is shifted left one position, so the 1 in the c propagates left wise. So in each iteration masking with the other variable you are able to know if there is a 1 or a 0 at that position of the variable.
Use in your code
You have
union temp
{
float f;
char c[4];
} k;
Inside the union the float and the char c[4] share the same memory location (as the property of union).
Now, sizeof (f) = 4bytes) You assign k.f = 5345341 or whatever . When you access the array k.arr[0] it will access the 0th byte of the float f, when you do k.arr[1] it access the 1st byte of the float f . The array is not empty as both the float and the array points the same memory location but access differently. This is actually a mechanism to access the 4 bytes of float bytewise.
NOTE THAT k.arr[0] may address the last byte instead of 1st byte (as told above), this depends on the byte ordering of storage in memory (See little endian and big endian byte ordering for this)
Union k
+--------+--------+--------+--------+ --+
| arr[0] | arr[1] | arr[2] | arr[3] | |
+--------+--------+--------+--------+ |---> Shares same location (in little endian)
| float f | |
+-----------------------------------+ --+
Or the byte ordering could be reversed
Union k
+--------+--------+--------+--------+ --+
| arr[3] | arr[2] | arr[1] | arr[0] | |
+--------+--------+--------+--------+ |---> Shares same location (in big endian)
| float f | |
+-----------------------------------+ --+
Your code loops on this and shifts the c which propagates the only 1 in the c from bit 7 to bit 0 in one step at a time in each location, and the bitwise anding checks actually every bit position of the bytes of the float variable f, and prints a 1 if it is 1 else 0.
If you print all the 4 bytes of the float, then you can see the IEEE 754 representation.

c has single bit in it set. 128 is 10000000 in binary. if(k.c[2] & c) checks if that bit is set in k.c[2] as well. Then the bit in c is shifted around to check for other bits.
As result the program is made to display the binary representation of float it seems.

Related

What does a bitwise AND do with no value infront of it?

I am using Verilog. Say you have the term:
& A
or
~& A
What does this do? Does it just compare it to an all empty array?
It performs a bitwise operation on all bits of the operand
e.g.:
//let x = 4’b1010
&x //equivalent to 1 & 0 & 1 & 0. Results in 1’b0
|x //equivalent to 1 | 0 | 1 | 0. Results in 1’b1
^x //equivalent to 1 ^ 0 ^ 1 ^ 0. Results in 1’b0
More about verilog operators: https://web.engr.oregonstate.edu/~traylor/ece474/beamer_lectures/verilog_operators.pdf

Odd bit operator in the increment statement of a for loop [duplicate]

This question already has answers here:
meaning of (number) & (-number)
(4 answers)
Closed 8 years ago.
Given this for loop:
for(++i; i < MAX_N; i += i & -i)
what is it supposed to mean? What does the statement i += i & -i accomplish?
This loop is often observed in binary indexed tree (or BIT) implementation which is useful to update range or point and query range or point in logarithmic time. This loop helps to choose the appropriate bucket based on the set bit in the index. For more details, please consider to read about BIT from some other source. In below post I will show how does this loop help to find the appropriate buckets based on the least significant set bits.
2s complementary signed system (when i is signed)
i & -i is a bit hack to quickly find the number that should be added to given number to make its trailing bit 0(that's why performance of BIT is logarithmic). When you negate a number in 2s complementary system, you will get a number with bits in inverse pattern added 1 to it. When you add 1, all the less significant bits would start inverting as long as they are 1 (were 0 in original number). First 0 bit encountered (1 in original i) would become 1.
When you and both i and -i, only that bit (least significant 1 bit) would remain set and all lesser significant (right) bits would be zero and more significant bits would be inverse of original number.
Anding would generate a power of 2 number that when added to number i would clear the least significant set bit. (as per the requirement of BIT)
For example:
i = 28
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
*
-i
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
I I I I I S Z Z
Z = Zero
I = Inverted
S = Same
* = least significant set bit
i & -i
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
Adding
+---+---+---+---+---+---+---+---+
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
x
x = cleared now
Unsigned (when i is unsigned)
It will work even for 1s complementary system or any other representation system as long as i is unsigned for the following reason:
-i will take value of 2sizeof(unsigned int) * CHAR_BITS - i. So all the bits right to the least significant set bit would remain zero, least significant bit would also remain zero, but all the bits after that would be inverted because of the carry bits.
For example:
i = 28
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
*
-i
0 1 1 1 1 1 <--- Carry bits
+---+---+---+---+---+---+---+---+
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
+---+---+---+---+---+---+---+---+
- | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
----------------------------------------
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
I I I I I S Z Z
Z = Zero
I = Inverted
S = Same
* = least significant set bit
i & -i
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
Adding
+---+---+---+---+---+---+---+---+
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
x
x = cleared now
Implementation without bithack
You can also use i += (int)(1U << __builtin_ctz((unsigned)i)) on gcc.
Live example here
A non obfuscated version for the same would be:
/* Finds smallest power of 2 that can reset the least significant set bit on adding */
int convert(int i) /* I purposely kept i signed as this works for both */
{
int t = 1, d;
for(; /* ever */ ;) {
d = t + i; /* Try this value of t */
if(d & t) t *= 2; /* bit at mask t was 0, try next */
else break; /* Found */
}
return t;
}
EDITAdding from this answer:
Assuming 2's complement (or that i is unsigned), -i is equal to ~i+1.
i & (~i + 1) is a trick to extract the lowest set bit of i.
It works because what +1 actually does is to set the lowest clear bit,
and clear all bits lower than that. So the only bit that is set in
both i and ~i+1 is the lowest set bit from i (that is, the lowest
clear bit in ~i). The bits lower than that are clear in ~i+1, and the
bits higher than that are non-equal between i and ~i.

Unset the rightmost set bit [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
How do you set, clear and toggle a single bit in C?
Removing lowest order bit
n is a positive integer. How can its rightmost set bit be unset?
Say n= 7 => n = 0111.
I want 0110 as the output. Is there any simple bitwise hack to achieve the goal?
Try n & (n-1) where & is bitwise AND
n = 7
n - 1 =6
n & (n-1)=> 0 1 1 1 (7)
& 0 1 1 0 (6)
---------
0 1 1 0 (done!)
EDIT (in response to the comment given by Forest)
n = 6
n - 1 = 5
n & (n-1)=> 0 1 1 0 (6)
& 0 1 0 1 (5)
---------
0 1 0 0 (done!)
Your question is unclear.
If you just want to unset bit 0, here are some methods (with slight variations in behavior depending on your types involved):
x &= -2;
x &= ~1;
x -= (x&1);
If you want to unset the lowest bit among the bits that are set, here are some ways:
x &= x-1;
x -= (x&-x);
Note that x&-x is equal to the lowest bit of x, at least when x is unsigned or twos complement. If you want to do any bit arithmetic like this, you should use only unsigned types, since signed types have implementation-defined behavior under bitwise operations.
unsigned int clr_rm_set_bit(unsigned int n)
{
unsigned int mask = 1;
while(n & mask) {
mask <<= 1;
}
return n & ~mask;
}

How to optimize a cycle?

I have the following bottleneck function.
typedef unsigned char byte;
void CompareArrays(const byte * p1Start, const byte * p1End, const byte * p2, byte * p3)
{
const byte b1 = 128-30;
const byte b2 = 128+30;
for (const byte * p1 = p1Start; p1 != p1End; ++p1, ++p2, ++p3) {
*p3 = (*p1 < *p2 ) ? b1 : b2;
}
}
I want to replace C++ code with SSE2 intinsic functions. I have tried _mm_cmpgt_epi8 but it used signed compare. I need unsigned compare.
Is there any trick (SSE, SSE2, SSSE3) to solve my problem?
Note:
I do not want to use multi-threading in this case.
Instead of offsetting your signed values to make them unsigned, a slightly more efficient way would be to do the following:
use _mm_min_epu8 to get the unsigned min of p1, p2
compare this min for equality with p2 using _mm_cmpeq_epi8
the resulting mask will now be 0x00 for elements where p1 < p2 and 0xff for elements where p1 >= p2
you can now use this mask with _mm_or_si128 and _mm_andc_si128 to select the appropriate b1/b2 values
Note that this is 4 instructions in total, compared with 5 using the offset + signed comparison approach.
You can subtract 127 from your numbers, and then use _mm_cmpgt_epi8
Yes, this can be done in SIMD, but it will take a few steps to make the mask.
Ruslik got it right, I think. You want to xor each component with 0x80 to flip the sense of the signed and unsigned comparison. _mm_xor_si128 (PXOR) gets you that -- you'll need to create the mask as a static char array somewhere before loading it into a SIMD register. Then _mm_cmpgt_epi8 gets you a mask and you can use a bitwise AND (eg _mm_and_si128) to perform a masked-move.
Yes, SSE will not work here.
You can improve this code performance on multi-core computer by using OpenMP:
void CompareArrays(const byte * p1Start, const byte * p1End, const byte * p2, byte * p3)
{
const byte b1 = 128-30;
const byte b2 = 128+30;
int n = p1End - p1Start;
#pragma omp parallel for
for (int i = 0; i < n; ++p1, ++i)
{
p3[i] = (p1[i] < p2[i]) ? b1 : b2;
}
}
Unfortunately, many of the answers above are incorrect. Let's assume a 3-bit word:
unsigned: 4 5 6 7 0 1 2 3 == signed: -4 -3 -2 -1 0 1 2 3 (bits: 100 101 110 111 000 001 010 011)
The method by Paul R is incorrect. Suppose we want to know if 3 > 2. min(3,2) == 2, which suggests yes, so the method works here. Now suppose we want to know if if 7 > 2. The value 7 is -1 in signed representation, so min(-1,2) == -1, which suggests wrongly that 7 is not greater than 2 unsigned.
The method by Andrey is also incorrect. Suppose we want to know if 7 > 2, or a = 7, and b = 2. The value 7 is -1 in signed representation, so the first term (a > b) fails, and the method suggests that 7 is not greater than 2.
However, the method by BJobnh, as corrected by Alexey, is correct. Just subtract 2^(n-1) from the values, where n is the number of bits. In this case, we would subtract 4 to obtain new corresponding values:
old signed: -4 -3 -2 -1 0 1 2 3 => new signed: 0 1 2 3 -4 -3 -2 -1 == new unsigned 0 1 2 3 4 5 6 7.
In other words, unsigned_greater_than(a,b) is equivalent to signed_greater_than(a - 2^(n-1), b - 2^(n-1)).
use pcmpeqb and be the Power with you.

c and c++ operators help

can someone explain to me why the following results in b = 13?
int a, b, c;
a = 1|2|4;
b = 8;
c = 2;
b |= a;
b&= ~c;
It is using binary manipultaors. (Assuming ints are 1 byte, and use Two's complement for storage, etc.)
a = 1|2|4 means a = 00000001 or 00000010 or 00000100, which is 00000111, or 7.
b = 8 means b = 00001000.
c = 2 means c = 00000010.
b |= a means b = b | a which means b = 00001000 or 00000111, which is 00001111, or 15.
~c means not c, which is 11111101.
b &= ~c means b = b & ~c, which means b = 00001111 and 11111101, which is 00001101, or 13.
http://www.cs.cf.ac.uk/Dave/C/node13.html
a = 1|2|4
= 0b001
| 0b010
| 0b100
= 0b111
= 7
b = 8 = 0b1000
c = 2 = 0b10
b|a = 0b1000
| 0b0111
= 0b1111 = 15
~c = 0b111...1101
(b|a) & ~c = 0b00..001111
& 0b11..111101
= 0b00..001101
= 13
lets go into binary mode:
a = 0111 (7 in decimal)
b = 1000 (8)
c = 0010 (2)
then we OR b with a to get b = 1111 (15)
c = 0010 and ~c = 1101
finally b is anded with negated c which gives us c = 1101 (13)
hint: Convert decimal to binary and give it a shot.. maybe... just maybe you'll figure it all out by yourself
a = 1 | 2 | 4;
Assigns the value 7 to a. This is because you are performing a bitwise OR operation on the constants 1, 2 and 4. Since the binary representation of each of these is 1, 10 and 100 respectively, you get 111 which is 7.
b |= a;
This ORs b and a and assigns the result to b. Since b's binary representation is now 111 and a's binary representation is 1000 (8), you end up with 1111 or 15.
b &= ~c;
The ~c in this expression means the bitwise negation of c. This essentially flips all 0's to 1's and vice versa in the binary representation of c. This means c switches from 10 to 111...11101.
After negating c, there is a bitwise AND operation between b and c. This means only bits that are 1 in both b and c remain 1, all others equal 0. Since b is now 1111 and c is all 1's except in the second lowest order bit, all of b's bits remain 1 except the 2 bit.
The result of flipping b's 2 bit is the same as if you simply subtracted 2 from its value. Since its current value is 15, and 15-2 = 13, the assignment results in b == 13.