Arithmetic shift
e substituted for an IDIV by power of two instruction nor vice versa.
Formal definition
The formal definition of an arithmetic shift, from Federal Standard 1037C is that it is:
- A shift, applied to the representation of a number in a fixed radix numeration system and in a fixed-point representation system, and in which only the characters representing the fixed-point part of the number are moved. An arithmetic shift is usually equivalent to multiplying the number by a positive or a negative integral power of the radix, except for the effect of any rounding; compare the logical shift with the arithmetic shift, especially in the case of floating-point representation.
An important word in the FS 1073C definition is "usually".
Equivalence of arithmetic and logical left shifts and multiplication
Arithmetic left shifts are equivalent to multiplication by a (positive, integral) power of the radix (e.g., a multiplication by a power of 2 for binary numbers). Logical left shifts are also equivalent, except multiplication and arithmetic shifts may trigger arithmetic overflow whereas logical shifts do not.
Non-equivalence of arithmetic right shift and division
However, arithmetic right shifts are major traps for the unwary, specifically in treating rounding of negative integers. For example, in the usual two's complement representation of negative integers, −1 is represented as all 1's. For an 8-bit signed integer this is 1111 1111. An arithmetic right-shift by 1 (or 2, 3, ..., 7) yields 1111 1111 again, which is still −1. This corresponds to rounding down (towards negative infinity), but is not the usual convention for division.
It is frequently stated that arithmetic right shifts are equivalent to division by a (positive, integral) power of the radix (e.g., a division by a power of 2 for binary numbers), and hence that division by a power of the radix can be optimized by implementing it as an arithmetic right shift. (A shifter is much simpler than a divider. On most processors, shift instructions will execute faster than division instructions.) Large number of 1960s and 1970s programming handbooks, manuals, and other specifications from companies and institutions such as DEC, IBM, Data General, and ANSI make such incorrect statements [1][page needed].
Logical right shifts are equivalent to division by a power of the radix (usually 2) only for positive or unsigned numbers. Arithmetic right shifts are equivalent to logical right shifts for positive signed numbers. Arithmetic right shifts for negative numbers in N−1's complement (usually two's complement) is roughly equivalent to division by a power of the radix (usually 2), where for odd numbers rounding downwards is applied (not towards 0 as usually expected).
Arithmetic right shifts for negative numbers are equivalent to division using rounding towards 0 in one's complement representation of signed numbers as was used by some historic computers, but this is no longer in general use.
Handling the issue in programming languages
The (1999) ISO standard for the programming language C defines the right shift operator in terms of divisions by powers of 2.[2] Because of the above-stated non-equivalence, the standard explicitly excludes from that definition the right shifts of signed numbers that have negative values. It does not specify the behaviour of the right shift operator in such circumstances, but instead requires each individual C compiler to define the behaviour of shifting negative values right.[note 1]
Applications
In applications where consistent rounding down is desired, arithmetic right shifts for signed values are useful. An example is in downscaling raster coordinates by a power of two, which maintains even spacing. For example, right shift by 1 sends 0, 1, 2, 3, 4, 5, ... to 0, 0, 1, 1, 2, 2, ..., and −1, −2, −3, −4, ... to −1, −1, −2, −2, ..., maintaining even spacing as −2, −2, −1, −1, 0, 0, 1, 1, 2, 2, ... In contrast, integer division with rounding towards zero sends −1, 0, and 1 all to 0 (3 points instead of 2), yielding −2, −1, −1, 0, 0, 0, 1, 1, 2, 2, ... instead, which is irregular at 0.
Notes
- ^ The C standard was intended to not restrict the C language to either ones' complement or two's complement architectures. In cases where the behaviours of ones' complement and two's complement representations differ, such as this, the standard requires individual C compilers to document the behaviour of their target architectures. The documentation for GNU Compiler Collection (GCC), for example, documents its behaviour as employing sign-extension.[3]
References
Cross-reference
- ^ Steele 1977.
- ^ ISOIEC9899 1999, § 6.5.7 Bitwise shift operators.
- ^ FSF 2008, § 4.5 Integers implementation.
Sources used
This article incorporates public domain material from Federal Standard 1037C. General Services Administration. Archived from the original on 2022-01-22.
- Knuth, Donald (1969). The Art of Computer Programming, Volume 2 — Seminumerical algorithms. Reading, Mass.: Addison-Wesley. pp. 169–170.
- Steele, Guy L. (November 1977). "Arithmetic shifting considered harmful". ACM SIGPLAN Notices archive. 12 (11). New York: ACM Press: 61–69. doi:10.1145/956641.956647. hdl:1721.1/6090.
- "3.7.1 Arithmetic Shift Operator". VAX MACRO and Instruction Set Reference Manual. Hewlett-Packard Development Company. April 2001. Archived from the original on 2011-08-08.
{{cite book}}
:|work=
ignored (help) - "Programming languages — C". ISO/IEC 9899:1999. International Organization for Standardization. 1999.
{{cite journal}}
: Cite journal requires|journal=
(help) - Hyde, Randall (1996-09-26). "CHAPTER SIX: THE 80x86 INSTRUCTION SET (Part 3)". The Art of ASSEMBLY LANGUAGE PROGRAMMING. Archived from the original on 2007-11-23. Retrieved 2007-11-28.
- "C Implementation". GCC manual. Free Software Foundation. 2008.