Logical shift

Last updated

In computer science, a logical shift is a bitwise operation that shifts all the bits of its operand. The two base variants are the logical left shift and the logical right shift. This is further modulated by the number of bit positions a given value shall be shifted, such as shift left by 1 or shift right by n. Unlike an arithmetic shift, a logical shift does not preserve a number's sign bit or distinguish a number's exponent from its significand (mantissa); every bit in the operand is simply moved a given number of bit positions, and the vacant bit-positions are filled, usually with zeros, and possibly ones (contrast with a circular shift).

A logical shift is often used when its operand is being treated as a sequence of bits instead of as a number.

Logical shift operators in various programming languages and processors
Language or processorLeftRight
Ada [1] Shift_LeftShift_Right
Batch, [2] C, C++, Go, Swift (unsigned types only);
Standard ML, Verilog, PHP, Python, [3] Rust [4] (unsigned types only [5] )
<< >>
D, Java, JavaScript, Julia << >>>
F# (unsigned types only)<<<>>>
Fortran LSHIFTRSHIFT
OCaml lsllsr
Object Pascal, Delphi, x86 assembly, Kotlin, Powershell shlshr
VHSIC Hardware Description Language (VHDL), MIPS sllsrl
PowerPC slwsrw

Logical shifts can be useful as efficient ways to perform multiplication or division of unsigned integers by powers of two. Shifting left by n bits on a signed or unsigned binary number has the effect of multiplying it by 2n. Shifting right by n bits on an unsigned binary number has the effect of dividing it by 2n (rounding towards 0).

Logical right shift differs from arithmetic right shift. Thus, many languages have different operators for them. For example, in Java and JavaScript, the logical right shift operator is >>>, but the arithmetic right shift operator is >>. (Java has only one left shift operator (<<), because left shift via logic and arithmetic have the same effect.)

The programming languages C, C++, and Go, however, have only one right shift operator, >>. Most C and C++ implementations, and Go, choose which right shift to perform depending on the type of integer being shifted: signed integers are shifted using the arithmetic shift, and unsigned integers are shifted using the logical shift. In particular, C++ uses its logical shift operators as part of the syntax of its input and output functions, called "cin" and "cout" respectively.

All currently relevant C standards (ISO/IEC 9899:1999 to 2011) leave a definition gap for cases where the number of shifts is equal to or bigger than the number of bits in the operands in a way that the result is undefined. This helps allow C compilers to emit efficient code for various platforms by allowing direct use of the native shift instructions which have differing behavior. For example, shift-left-word in PowerPC chooses the more-intuitive behavior where shifting by the bit width or above gives zero, [6] whereas SHL in x86 chooses to mask the shift amount to the lower bits to reduce the maximum execution time of the instructions, and as such a shift by the bit width doesn't change the value. [7]

Some languages, such as the .NET Framework and LLVM, also leave shifting by the bit width and above unspecified (.NET) [8] or undefined (LLVM). [9] Others choose to specify the behavior of their most common target platforms, such as C# which specifies the x86 behavior. [10]

Example

If the bit sequence 0001 0111 (decimal 23) is logically shifted by one bit position, then:

Shift left yields: 0010 1110 (decimal 46)
Logical left shift one bit Rotate left logically.svg
Logical left shift one bit
Shift right yields: 0000 1011 (decimal 11)
Logical right shift one bit Rotate right logically.svg
Logical right shift one bit

Note: MSB = Most Significant Bit, LSB = Least Significant Bit

Related Research Articles

<span class="mw-page-title-main">Arithmetic shift</span> Shift operator in computer programming

In computer programming, an arithmetic shift is a shift operator, sometimes termed a signed shift. The two basic types are the arithmetic left shift and the arithmetic right shift. For binary numbers it is a bitwise operation that shifts all of the bits of its operand; every bit in the operand is simply moved a given number of bit positions, and the vacant bit-positions are filled in. Instead of being filled with all 0s, as in logical shift, when shifting to the right, the leftmost bit is replicated to fill in all the vacant positions.

x86 assembly language is the name for the family of assembly languages which provide some level of backward compatibility with CPUs back to the Intel 8008 microprocessor, which was launched in April 1972. It is used to produce object code for the x86 class of processors.

In computer programming, a bitwise operation operates on a bit string, a bit array or a binary numeral at the level of its individual bits. It is a fast and simple action, basic to the higher-level arithmetic operations and directly supported by the processor. Most bitwise operations are presented as two-operand instructions where the result replaces one of the input operands.

Two's complement is the most common method of representing signed integers on computers, and more generally, fixed point binary values. Two's complement uses the binary digit with the greatest place value as the sign to indicate whether the binary number is positive or negative. When the most significant bit is 1, the number is signed as negative; and when the most significant bit is 0 the number is signed as positive.

In computer science, primitive data types are a set of basic data types from which all other data types are constructed. Specifically it often refers to the limited set of data representations in use by a particular processor, which all compiled programs must use. Most processors support a similar set of primitive data types, although the specific representations vary. More generally, "primitive data types" may refer to the standard data types built into a programming language. Data types which are not primitive are referred to as derived or composite.

In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres. This is different from unspecified behavior, for which the language specification does not prescribe a result, and implementation-defined behavior that defers to the documentation of another component of the platform.

This is a list of operators in the C and C++ programming languages. All the operators listed exist in C++; the column "Included in C", states whether an operator is also present in C. Note that C does not support operator overloading.

The Hamming weight of a string is the number of symbols that are different from the zero-symbol of the alphabet used. It is thus equivalent to the Hamming distance from the all-zero string of the same length. For the most typical case, a string of bits, this is the number of 1's in the string, or the digit sum of the binary representation of a given number and the ₁ norm of a bit vector. In this binary case, it is also called the population count, popcount, sideways sum, or bit summation.

<span class="mw-page-title-main">Circular shift</span>

In combinatorial mathematics, a circular shift is the operation of rearranging the entries in a tuple, either by moving the final entry to the first position, while shifting all other entries to the next position, or by performing the inverse operation. A circular shift is a special kind of cyclic permutation, which in turn is a special kind of permutation. Formally, a circular shift is a permutation σ of the n entries in the tuple such that either

<span class="mw-page-title-main">Integer overflow</span> Computer arithmetic error

In computer programming, an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of digits – either higher than the maximum or lower than the minimum representable value.

A bit field is a data structure that consists of one or more adjacent bits which have been allocated for specific purposes, so that any single bit or group of bits within the structure can be set or inspected. A bit field is most commonly used to represent integral types of known, fixed bit-width, such as single-bit Booleans.

Bit manipulation is the act of algorithmically manipulating bits or other pieces of data shorter than a word. Computer programming tasks that require bit manipulation include low-level device control, error detection and correction algorithms, data compression, encryption algorithms, and optimization. For most other tasks, modern programming languages allow the programmer to work directly with abstractions instead of bits that represent those abstractions.

Signed zero is zero with an associated sign. In ordinary arithmetic, the number 0 does not have a sign, so that −0, +0 and 0 are equivalent. However, in computing, some number representations allow for the existence of two zeros, often denoted by −0 and +0, regarded as equal by the numerical comparison operations but with possible different behaviors in particular operations. This occurs in the sign-magnitude and ones' complement signed number representations for integers, and in most floating-point number representations. The number 0 is usually encoded as +0, but can still be represented by +0, −0, or 0.

In computer processors, the overflow flag is usually a single bit in a system status register used to indicate when an arithmetic overflow has occurred in an operation, indicating that the signed two's-complement result would not fit in the number of bits used for the result. Some architectures may be configured to automatically generate an exception on an operation resulting in overflow.

In computer processors the carry flag is a single bit in a system status register/flag register used to indicate when an arithmetic carry or borrow has been generated out of the most significant arithmetic logic unit (ALU) bit position. The carry flag enables numbers larger than a single ALU width to be added/subtracted by carrying (adding) a binary digit from a partial addition/subtraction to the least significant bit position of a more significant word. This is typically programmed by the user of the processor on the assembly or machine code level, but can also happen internally in certain processors, via digital logic or microcode, where some processors have wider registers and arithmetic instructions than ALU. It is also used to extend bit shifts and rotates in a similar manner on many processors. For subtractive operations, two (opposite) conventions are employed as most machines set the carry flag on borrow while some machines instead reset the carry flag on borrow.

The zero flag is a single bit flag that is a central feature on most conventional CPU architectures. It is often stored in a dedicated register, typically called status register or flag register, along with other flags. The zero flag is typically abbreviated Z or ZF or similar in most documentation and assembly languages.

LEB128 or Little Endian Base 128 is a variable-length code compression used to store arbitrarily large integers in a small number of bytes. LEB128 is used in the DWARF debug file format and the WebAssembly binary encoding for all integer literals.

<span class="mw-page-title-main">Arithmetic logic unit</span> Combinational digital circuit

In computing, an arithmetic logic unit (ALU) is a combinational digital circuit that performs arithmetic and bitwise operations on integer binary numbers. This is in contrast to a floating-point unit (FPU), which operates on floating point numbers. It is a fundamental building block of many types of computing circuits, including the central processing unit (CPU) of computers, FPUs, and graphics processing units (GPUs).

In computer software and hardware, find first set (ffs) or find first one is a bit operation that, given an unsigned machine word, designates the index or position of the least significant bit set to one in the word counting from the least significant bit position. A nearly equivalent operation is count trailing zeros (ctz) or number of trailing zeros (ntz), which counts the number of zero bits following the least significant one bit. The complementary operation that finds the index or position of the most significant set bit is log base 2, so called because it computes the binary logarithm ⌊log2(x)⌋. This is closely related to count leading zeros (clz) or number of leading zeros (nlz), which counts the number of zero bits preceding the most significant one bit. There are two common variants of find first set, the POSIX definition which starts indexing of bits at 1, herein labelled ffs, and the variant which starts indexing of bits at zero, which is equivalent to ctz and so will be called by that name.

In the C programming language, operations can be performed on a bit level using bitwise operators.

References

  1. Annotated Ada Reference Manual
  2. https://ss64.com/nt/set.html
  3. "BitwiseOperators - Python Wiki". wiki.python.org. Retrieved 2018-01-24.
  4. "Shl in std::ops - Rust". doc.rust-lang.org. Retrieved 2022-01-17.
  5. "Operator Expressions: Arithmetic and Logical Binary Operators". doc.rust-lang.org. Retrieved 2022-11-13.
  6. "PowerPC Instruction Set: slw". pds.twi.tudelft.nl. Retrieved 9 April 2016.
  7. "x86 Instruction Set Reference". x86.renejeschke.de. Retrieved 9 April 2016.
  8. "Opcodes.Shl Field". msdn.microsoft.com. Microsoft. Retrieved 9 April 2016.
  9. "LLVM Language Reference Manual - shl Instruction". llvm.org. LLVM Project. Retrieved 9 April 2016.
  10. "<< Operator (C# Reference)". msdn.microsoft.com. Microsoft. Retrieved 9 April 2016.