Could anyone please explain me what exactly the following line of code produce?
i = 1<<(sizeof(n) * 8 - 1);
You can assume whatever value you want for 'n'. I am trying to implement an 8 bit multiplication program using Booths algorithm.
Let's break it down:
sizeof(n) delivers the size of the type of variable n. For an int variable n on a 32 bit system, this would e.g. be 4 (bytes). See the sizeof documentation e.g. here: http://en.cppreference.com/w/cpp/keyword/sizeof)
* 8 -> multiplication by the number of bits in one byte -> i.e. sizeof(n) * 8 delivers the number of bits necessary for n.
<< is the shiftleft operator. It will shift the first operand to the left by the amount of bits specified by the second operand (see here: http://en.wikipedia.org/wiki/Logical_shift); it's the logical shift, meaning that bits shifted in from the right are filled up with zeroes.
The full expression therefore delivers an expresssion with the highest bit representable by the variable n set to 1.
Example (assuming n now to be of type char, and assuming the size of char as the typical 1 byte):
sizeof(char) = 1
=> sizeof(char) * 8 - 1 = 7
=> 1 << 7 = 10000000
Related
What does & ~(minOffsetAlignment - 1) mean?
Does it mean address of destructor?
This is the code snippet I got it from.
VkDeviceSize is uint64_t.
VkDeviceSize getAlignment(VkDeviceSize instanceSize, VkDeviceSize minOffsetAlignment)
{
if (minOffsetAlignment > 0)
{
return (instanceSize + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1);
}
return instanceSize;
}
It's a common trick to align a certain number to a certain boundary. It assumes that minOffsetAlignment is a power of two.
If minOffsetAlignment is a power of two, its binary form will be a one followed by zeros. For example if 8, the binary will be b00001000.
If you subtract one, it will become a mask where all the bits that can be changed will be flagged as one. For the same example, it will be b00000111 (all numbers from 0 to 7).
If you take the complement of this number, it becomes a mask for clearing. In the example, b11111000.
If you AND (&) any number against this mask, it will have the effect to zero all the bits relative to numbers below the alignment.
For example, say I have the number 9 b00001001. Doing 9&7 is b00001001 & b11111000 which results in b00001000 or 8.
The resulting value is the computed value aligned for the given amount.
What does &~ mean?
In this case, & is the bitwise and operator. It is a binary operator. Each bit of the result is set if the corresponding bit is set for both operands, otherwise the bit is unset. In this case, the left hand operand is (instanceSize + minOffsetAlignment - 1) and the right hand operand is ~(minOffsetAlignment - 1)
~ is the bitwise not operator. It is a unary operator. Each bit of the result is set if the corresponding bit is unset in the operand, otherwise the bit is unset. In this case, the operand is (minOffsetAlignment - 1)
The idea of this code is to say, "Given a particular (object) instance size, how many bytes of memory are used if the allocator has to round-up object sizes to some power-of-two multiple." Note that if the instance size is already a multiple of the power of two (e.g. 8), then no rounding-up is needed.
It is often the case that memory needs to be allocated in multiples of the hardware's word size in bytes. On a 32-bit platform that would mean a multiple of 4, on 64-bit, a multiple of 8. Note however that the multiple (and thus minOffsetAlignment) must be a power of 2 (the author of this code, for better or worse, is 100% assuming the person calling this function knows this).
Let's assume for the rest of my answer that we're working with a hardware word size of 64-bit, and that our platform must allocate memory in chunks of 8 bytes (64 bits divided by 8 bits per byte == 8 bytes). So minOffsetAlignment will be passed as 8.
Consequently, if the instance size is 1-8 bytes, our function must return 8. If it's 9-16 bytes, it must return 16, and so on.
This answer shows how to round up a value to some nearest integer provided the value being rounded isn't already a multiple of that integer.
In the case of rounding up to the nearest multiple of 8, the procedure is to add 7, then do integer division to divide by 8, then multiply by 8.
So:
(0 + 7) / 8 * 8 == 0 // a zero-byte instance requires zero memory bytes
(1 + 7) / 8 * 8 == 8 // a one-byte instance requires eight memory bytes
(2 + 7) / 8 * 8 == 8 // a two-byte instance requires eight memory bytes
...
(8 + 7) / 8 * 8 == 8 // an eight-byte instance requires eight memory bytes
(9 + 7) / 8 * 8 == 16 // a nine-byte instance requires sixteen memory bytes
...
What the code in your question is doing is exactly the above algorithm, but it's using bitwise operations instead of addition, division, and multiplication which on some hardware is faster.
Now, how does it do this?
First we have to get the (instanceSize + 7) part. That's here:
(instanceSize + minOffsetAlignment - 1)
Then we have to divide it by 8, truncate the remainder, and multiply the result of the division by 8.
The last part does that all in one step, and this explains why minOffsetAlignment had to be a power of two.
First, we see:
minOffsetAlignment - 1
If minOffsetAlignment is 8, then its binary value is 0b00001000.
Subtracting 1 from 8 gives 7, which in binary is 0b00000111.
Now the complement of 7 is taken:
~(minOffsetAlignment - 1)
This inverts all the bits so we get ...1111000 (for a 64-bit integer such as VkDeviceSize there are 61 leading 1's and 3 trailing 0's).
Now, putting the whole statement together:
(instanceSize + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1)
We see the & operator will clear the last three bits of whatever the result of (instanceSize + minOffsetAlignment - 1) is.
This forces the return value to be a multiple of 8 (since any binary integer with the last three bits 0 is a multiple of 8), but given that we already added 7 it also rounded it up to the nearest multiple of 8 provided instanceSize wasn't already a multiple of 8.
I am trying to understand what is happening in this bitwise operation that is used to set the size of a char array but I do not fully understand it.
unsigned long maxParams = 2;// or some other value, I just chose 2 arbitrarily
unsigned char m_uParamBitArray[(((maxParams) + ((8)-1)) & ~((8)-1))/8];
What size is this array set to based on the value of maxParams?
This counts the number of 8-bit chars needed to fit maxParams bits.
+7 is to round up to the next multiple of 8.
0 -> 7 will round to 0 char
1 -> 8 will round to 1 char
After division by 8. Which is done by /8
The bitwise and is to discard the last three bits before dividing by 8.
When maxParams is not divisible by eight, the first part of the formula formula rounds it up to the next multiple of eight; otherwise, it leaves the number unchanged. The second part of the formula divides the result by eight, which it can always do without getting a remainder.
In general, if you want to round up to N without going over it, you can add N-1 before the division:
(x + (N - 1)) / N
You can safely drop the & ~((8)-1) part of the expression:
(maxParams + (8-1))/8
To answer this question, I read this source code on github and found a problem with the second function.
The challenge is to write C code with various restrictions in terms of operators and language constructions to perform given tasks.
/*
* fitsShort - return 1 if x can be represented as a
* 16-bit, two's complement integer.
* Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int fitsShort(int x) {
/*
* after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
* so after shift, if x remains the same, then it means that x can be represent as 16-bit
*/
return !(((x << 16) >> 16) ^ x);
}
Left shifting a negative value or a number whose shifted value is beyond the range of int has undefined behavior, right shifting a negative value is implementation defined, so the above solution is incorrect (although it is probably the expected solution).
Is there a solution to this problem that only assumes 32-bit two's complement representation?
The following only assumes 2's complement with at least 16 bits:
int mask = ~0x7FFF;
return !(x&mask)|!(~x&mask);
That uses a 15-bit constant; if that is too big, you can construct it from three smaller constants, but that will push it over the 8-operator limit.
An equivalent way of writing that is:
int m = 0x7FFF;
return !(x&~m)|!~(x|m);
But it's still 7 operations, so int m = (0x7F<<8)|0xFF; would still push it to 9. (I only added it because I don't think I've ever before found a use for !~.)
I saw the following line of code here in C.
int mask = ~0;
I have printed the value of mask in C and C++. It always prints -1.
So I do have some questions:
Why assigning value ~0 to the mask variable?
What is the purpose of ~0?
Can we use -1 instead of ~0?
It's a portable way to set all the binary bits in an integer to 1 bits without having to know how many bits are in the integer on the current architecture.
C and C++ allow 3 different signed integer formats: sign-magnitude, one's complement and two's complement
~0 will produce all-one bits regardless of the sign format the system uses. So it's more portable than -1
You can add the U suffix (i.e. -1U) to generate an all-one bit pattern portably1. However ~0 indicates the intention clearer: invert all the bits in the value 0 whereas -1 will show that a value of minus one is needed, not its binary representation
1 because unsigned operations are always reduced modulo the number that is one greater than the largest value that can be represented by the resulting type
That on a 2's complement platform (that is assumed) gives you -1, but writing -1 directly is forbidden by the rules (only integers 0..255, unary !, ~ and binary &, ^, |, +, << and >> are allowed).
You are studying a coding challenge with a number of restrictions on operators and language constructions to perform given tasks.
The first problem is return the value -1 without the use of the - operator.
On machines that represent negative numbers with two's complement, the value -1 is represented with all bits set to 1, so ~0 evaluates to -1:
/*
* minusOne - return a value of -1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 2
* Rating: 1
*/
int minusOne(void) {
// ~0 = 111...111 = -1
return ~0;
}
Other problems in the file are not always implemented correctly. The second problem, returning a boolean value representing the fact the an int value would fit in a 16 bit signed short has a flaw:
/*
* fitsShort - return 1 if x can be represented as a
* 16-bit, two's complement integer.
* Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int fitsShort(int x) {
/*
* after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
* so after shift, if x remains the same, then it means that x can be represent as 16-bit
*/
return !(((x << 16) >> 16) ^ x);
}
Left shifting a negative value or a number whose shifted value is beyond the range of int has undefined behavior, right shifting a negative value is implementation defined, so the above solution is incorrect (although it is probably the expected solution).
Loooong ago this was how you saved memory on extremely limited equipment such as the 1K ZX 80 or ZX 81 computer. In BASIC, you would
Let X = NOT PI
rather than
LET X = 0
Since numbers were stored as 4 byte floating points, the latter takes 2 bytes more than the first NOT PI alternative, where each of NOT and PI takes up a single byte.
There are multiple ways of encoding numbers across all computer architectures. When using 2's complement this will always be true:~0 == -1. On the other hand, some computers use 1's complement for encoding negative numbers for which the above example is untrue, because ~0 == -0. Yup, 1s complement has negative zero, and that is why it is not very intuitive.
So to your questions
the ~0 is assigned to mask so all the bits in mask are equal 1 -> making mask & sth == sth
the ~0 is used to make all bits equal to 1 regardless of the platform used
you can use -1 instead of ~0 if you are sure that your computer platform uses 2's complement number encoding
My personal thought - make your code as much platform-independent as you can. The cost is relatively small and the code becomes fail proof
I have the following problem I am unable to solve gracefully.
I have a data type that can take 3 possible values (0,1,2).
I have an array of 20 element of this data type.
As I want to encode the information on the least amount of memory, I did the following :
consider that each element can take up to 4 values (2 bits)
each char holds 8 bits, so I can put 4 times an element
5 char holds 40 bits, so I can store 20 elements.
I have done this and it works time.
However I'm interested evaluating the space gained by using the fact that my element can only take 3 values and not 4.
Every possible combination gives us 3 to the 20th power, which is 3,486,784,401. However 256 to the 4th power gives us 4,294,967,296 , which is greater. This means I could encode my data on 4 char .
Is there an generic method to do the 2nd idea here ? The 1st idea is simple to implement with bit mask / bit shifts. However since 3 values doesn't fit in an integer number of bits, I have no idea how to encode / decode any of these values into an array of 4 char.
Do you have any idea or reference on how it's done ? I think there must be a general method. If anything I'm interested about the feasability of this
edit : this could be simplified to : how to store 5 values from 0 to 2 into 1 byte only (as 256 >= 3^5 = 243)
You should be able to do what you said using 4 bytes. Assume that you store the 20 values into a single int32_t called value, here is how you would extract any particular element:
element[0] = value % 3;
element[1] = (value / 3) % 3;
element[2] = (value / 9) % 3;
...
element[19] = (value / 1162261467) % 3; // 1162261467 = 3 ^ 19
Or as a loop:
for (i=0;i<20;i++) {
element[i] = value % 3;
value /= 3;
}
To build value from element, you would just do the reverse, something like this:
value = 0;
for (i=19;i>=0;i--)
value = value * 3 + element[i];
There is a generic way to figure out how much bits you need:
If your data type has N different values, then you need log(N) / log(2) bits to store this value. For instance in your example, log(3) / log(2) equals 1.585 bits.
Of course in reality you will to pack a fixed amount of values in an integer number of bits, so you have to multiply this 1.585 with that amount and round up. For instance if you pack 5 of them:
1.585 × 5 = 7.925, meaning that 5 of your values just fit in one 8-bit char.
The way to unpack the values has been shown in JS1's answer. The generic formula for unpacking is element[i] = (value / (N ^ i) ) mod N
Final note, this is only meaningful if you really need to optimize memory usage. For comparison, here are some popular ways people pack these value types. Most of the time the extra space taken up is not a problem.
an array of bool: uses 8 bits to store one bool. And a lot of people really dislike the behavior of std::vector<bool>.
enum Bla { BLA_A, BLA_B, BLA_C}; an array or vector of Bla probably uses 32 bits per element (sizeof(Bla) == sizeof(int)).