How Can I represent bitwise AND, OR Operations and Shift Operations using PsuedoCode?
Please Hep me
You said bitwise, so why not & (AND) | (OR) and << (left shift) or >> (right shift)?
Fairly universal C-style syntax.
If you want to represent implementations of bitwise operations, you can introduce "bit enumerator" (some kind of object to iterate over that will emit bits from the less significant one to the most significant for given number) and use mapping for arguments to result (like AND and OR definition suggests).
Related
I know that it is possible to use the left shift to implement multiplication by the power of two (x << 4 = x * 16).
Also, it is trivial to replace the right shift by division by a power of two (x >> 5 = x / 32).
I am wondering is it possible to replace the right shift with multiplication?
It seems to be not possible in the general case, but my question is limited to modulo 2^32 and 2^64 arithmetic (unsigned 32-bit and 64-bit values). Also, maybe it can be done if we can add other cheap instructions like + and - in addition to * to emulate the right bit shift?
I assume exotic architecture where the right shift is more expensive than other arithmetic (similar to division).
uint64_t foo(uint64_t x) {
return x >> 3; // how to avoid using right shift here?
}
There is a similar question How to perform right shifting binary multiplication? that asks how to replace multiplication of two unsigned numbers by right shift. Basically, it uses a loop internally. However, maybe if the second number is a constant, this loop can be avoided (or at least unrolled to a shorter fragment)?
"Multiply-high" aka high-mul, hmul, mulh, etc, can be used to emulate a shift-right with a constant count. Usually that's not a good trade. It's also hardly related to C++.
Normal multiplication (putting floating point stuff aside) cannot be used to implement a shift-right.
my question is limited to modulo 2^32 and 2^64 arithmetic
It doesn't help. You can use that property to "unmultiply" (sort of like divide, except not really) by odd numbers, for example if b = 5 * a then a = b * 0xCCCCCCCD, using the modular multiplicative inverse. The number being inverted must be relatively-prime relative to the modulus. Since the modulus is a power of two, the "divisor" here cannot be a power of two (except 1, but that does nothing), so a shift-right cannot be done this way.
Another way to look at it (probably simpler), is that what a multiplication does is conditionally add together a bunch of left-shifted versions of the multiplicand. Only left-shift versions, not right-shifted versions. Which of those shifted versions are selected by the multiplier doesn't matter, there are no right-shifted versions to select.
I'm aware of the two complement representation. I was wondering what are the specifics differences, in terms of implementation between int and unsigned int. I would than say that
Comparison is different (the sign bit will change how the comparison is performed).
Multiplication is different (I take the modulus, multiply such modules and complement the result based on the sign of both operands).
Division is different (same reason of multiplication).
Addition and subtraction look the same
Are there any other differences that maybe I'm not aware of?
I'm assuming two-complement arithmetic as this is the most common.
There are plenty of explanations of twos complement arithmetic out there. For example, links in the comments, and here for multiplication: http://pages.cs.wisc.edu/~smoler/cs354/beyond354/int.mult.html
1: Correct. Comparison is typically implemented the same as subtraction - but the results of the subtraction are discarded and only the status bits are used. Nit-pick: "<" and ">" are different, but "==" and "!=" are the same.
2, 3: Yes, multiplication and division are different.
4: Well, sort of. The bit-pattern of the result is the same, but there are important differences. The add/sub instructions on a typical processor set status flags for overflow, carry, negative and zero. So the difference I suppose is how you interpret the results rather than the results themselves. These status bits are not available to a C/C++ program, but are used by the code generated by the compiler.
5: Extension. Casting to a wider type is different. For unsigned integrals, they are "zero extended", while for signed integrals they are "sign extended". Sign extension means that it will copy the high order bit (the sign bit) of the narrow type to fill in the additional bits of the wide type.
6: Range: For example, the range of values for an unsigned 8-bit is 0...255, while for a signed 8-bit value it is -128...+127.
7: bit-wise operations "&", "|", "~", and "^" are the same
8: bit-shift operations "<<" and ">>": Left shift is the same, but right-shift is different as signed values right shifted do sign extension.
I know that this operator does the "AND logical operator" but I don't know how to deal with it and if it deals with decimal numbers or just binary numbers ?
It is the the XOR operator:
XOR (Exclusive Or)
This operation is performed between two bits (a and b). The result is
1 if either one of the two bits is 1, but not in the case that both
are. There for, if neither or both of them are equal to 1 the result
is 0.
That is the bitwise XOR operator.
It performs an exclusive or operation.
It is not the logical AND, it's the bitwise XOR. It operates on integers, which are always binary numbers in C++, and may be overloaded for other types.
That's the bitwise XOR operator (so not logical, not AND) and decimal numbers are represented as binaries, so of course it works for them as well.
The logical AND is && and the bitwise AND is &.
In this blog post the author has suggested the following as the bug fix:
int mid = (low + high) >>> 1;
Does anyone know what is this >>> operator? Certainly its not there on the following operator reference list:
http://msdn.microsoft.com/en-us/library/x04xhy0h%28v=vs.71%29.aspx
http://www.cplusplus.com/doc/tutorial/operators/
What is it and how does that solve the overflow problem?
>>> is not a part of C++. The blog contains code in Java.
Check out Java online tutorial here on Bitwise shift operators. It says
The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.
>>> is the logical right shift operator in Java.
It shifts in a zero on the left rather than preserving the sign bit. The author of the blog post even provides a C++ implementation:
mid = ((unsigned int)low + (unsigned int)high)) >> 1;
... if you right-shift unsigned numbers, preserving the sign bit doesn't make any sense (since there is no sign bit) so the compiler obviously uses logical shifts rather than arithmetic ones.
The above code exploits the MSB (32rd bit assuming 32 bit integers): adding low and high which are both nonnegative integers and fit thus into 31 bits never overflows the full 32 bits, but it extends to the MSB. By shifting it to the right, the 32 bit number is effectively divided by two and the 32rd bit is cleared again, so the result is positive.
The truth is that the >>> operator in Java is just a workaround for the fact that the language does not provide unsigned data types.
The >>> operator is in a Java code snippet, and it is the unsigned right shift operator. It differs from the >> operator in its treatment of signed values: the >> operator applies sign extension during the shift, while the >>> operator just inserts a zero in the bit positions "emptied" by the shift.
Sadly, in C++ there's no such thing as sign-preserving and unsigned right shift, we have only the >> operator, whose behavior on negative signed values is implementation-defined. To emulate a behavior like the one of >>> you have to perform some casts to unsigned int before applying the shift (as shown in the code snippet immediately following the one you posted).
The Java expression x >>> y is more or less equivalent to the C++ expression unsigned(x) >> y.
>>> is not C++ operator. I think it's an operator in Java language. I'm not sure though!
EDIT:
Yes. That is java operator. Check out the link to the article you provided. The article is using Java language!
It is a java operator, not related to C++.
However all the blog author does is change the division by 2 with a bit-wise right shift (i.e. right shifting the value by 1 is similar to dividing by 2 ^ 1).
Same functionality, different machine code output (bit shifting operations are almost always faster than multiplication/division on most architectures).
I understand bitwise operations and how they might be useful for different purposes, e.g. permissions. However, I don't seem to understand what use the bit shift operators are. I understand how they work, but I can't think of any scenarios where I might want to use them unless I want to do some really quick multiplication or division. Are there any other reasons to use bit-shifting?
There are many reasons, here are some:
Let's say you represent a black and white image as a sequence of bits and you want to set a single pixel in this image generically. For example your byte offset may be x>>3 and your bit offset may be x & 0x7 and you can set that bit by: byte = byte | (1 << (x & 0x7));
Implementing data compression algorithms where you deal with variable length bit sequences, e.g. huffman coding.
You're are interacting with some hardware, e.g. a serial communication device, and you need to read or set some control bits.
For those and other reasons most processors have bit shift and/or rotation instructions as well as other logic instructions (and/or/xor/not).
Historically multiplication and division were significantly slower as they are more complex operations and some CPUs didn't have those at all.
Also see here:
Have you ever had to use bit shifting in real projects?
As you indicate, a left shift is the same thing as a multiplication by two. At least it is when we're talking about unsigned quantities. The meaning of a "left shift" of a signed quantity is ... language dependent.
With modern compilers, there's really no difference between writing "i = x*2;" and "i = x << 1;" The compiler will generate the most efficient code. So in that sense there's no reason to prefer shift over multiply.
Some algorithms work by shifting a quantity left by one bit and then setting the low bit to either 0 or 1. Some simple compression algorithms work this way. For example, if your accumulated value is in the variable x, and the current value (0 or 1) is in y, then it makes more sense to write "x = (x << 1) | y", rather than "x = (x * 2) + y". Both do the same thing, but the first is more notationally correct. You don't have to think, "oh, right, multiply by two is the same as a left shift."
Also, when you're talking about algorithms that shift bits, it's more convenient to shift left or right by a particular number of bits than to figure out what multiple of 2 you want to multiply or divide by.
So, whereas there's typically no performance benefit to shifting rather than multiplying--at least not when working with high level languages--there are times when having the ability to shift makes what you're doing more easily understood.
There are lot of places where bit shift operations are regularly used outside of their usage in numerical computations. For example, Bitboard is a data structure that is commonly used in board games for board representation. Some of the strongest chess engines use this data structure mainly for speed and ease of move generation and evaluation. These programs use bit operations heavily and bit-shift operations specifically are used in a lot of contexts - such as finding bit masks, generating new moves on the board, computing logarithm very quickly, etc. There are even very advanced numerical computations that can be done elegantly by clever use of bit operations. Check out this site for bit twiddling hacks - a lot of those algorithms use shift operators. Bit shift operations are regularly used in device driver programming, codec development, embedded systems programming and so on.
Shifting allows accessing specific bits within a variable. The expression (n >> p) & ((1 << m) - 1) retrieves an m-bit portion of the variable n with an offset of p bits from the right.
This allows your program to use integers that aren't multiples of 8 bits, which is useful for data compression.
For example, I used it in my Netflix Prize programs to pack records (22-bit user ID + 15-bit movie ID + 12-bit date + 3-bit rating) into a uint64_t (with 12 bits to spare).
A very common special case is to pack 8 bool variables into each byte. (Unix file permissions, black-and-white bitmaps, CPU flags registers, etc.)
Also, bit manipulation is used in UTF-8, which is a very popular character encoding. Unicode characters are represented by distributing their bits across 1, 2, 3, or 4 bytes.