4-10  A NOTE ON INTEGERS 
 ************************

 Signed and unsigned integers
 ----------------------------
 FORTRAN integers are SIGNED INTEGERS, half the possible bit patterns 
 are used to represent positive values (and 0), the other half is used 
 for the negative values.

 A table showing the bit patterns that can be constructed with 4 bits,
 and the integers that are associated with them:

   Bit             Signed      Unsigned
   Pattern         integer     integer
   ------------    --------    --------
    1111             -1          15
    1110             -2          14
    1101             -3          13
    1100             -4          12
    1011             -5          11
    1010             -6          10
    1001             -7           9
    1000             -8           8
    0111              7           7
    0110              6           6
    0101              5           5
    0100              4           4
    0011              3           3
    0010              2           2
    0001              1           1
    0000              0           0

 Of course no FORTRAN integer type is really made of half a byte, 
 but that is enough to illustrate the general principles. 

 CPU hardware adds integers bit by bit, from the Least Significant
 Bit (LSB) to the Most Significant Bit (MSB), taking into account
 the value carried from the previous binary bit addition.

 We will call the correspondence between the possible bit patterns
 and unsigned integers the natural representation.



 Natural binary representation of positive integers
 --------------------------------------------------
 The binary representation of a positive integer N is:

    N = A0*1 + A1*2 + A2*4 + A3*8 + A4*16 + ...     Ai = {0,1}

 The Ai coefficients are the reminders on repeated divisions 
 by 2:

    A0 = N - (2 * (N / 2)) = MOD(N, 2)
    N  = N / 2
    A1 = N - (2 * (N / 2)) = MOD(N, 2)
    ......................

 The resulting binary number can be written:

    ... A4 A3 A2 A1 A0



 Other binary representations of positive integers
 -------------------------------------------------
 Two more representation methods were invented for positive integers, 
 offset binary and the binary coded decimal family (BCD). 

 These methods are better understood in the context of extending the
 representation to include negative integers, and so will be discussed
 in the next paragraph.



 Number systems that include negative & positive integers
 --------------------------------------------------------
 Extending the 'natural' binary representation of positive integers 
 to negative integers can be done in at least 3 different schemes: 
 sign-magnitude, one's complement and two's complement.

   SIGN-MAGNITUDE    The most significant bit (MSB) is reserved to 
                     the sign, 0 is positive, 1 is negative.
                     All other bits are used to store the
                     magnitude in the natural representation.
                     Addition and subtraction are complicated. 
                     There are two representations for zero!

   ONE'S COMPLEMENT  Positive integers are like in the natural
                     representation, negative numbers are obtained
                     by complementing each bit of the corresponding
                     positive number (i.e. the absolute value)
                     There are two representations for zero!
                     Bitwise addition of  N  and  -N  gives -0.
                     Positive integers still have MSB = 0, and 
                     negative integers have MSB=1.

   TWO'S COMPLEMENT  Like one's complement, but negative numbers
                     are having 1 added after complementation.
                     Bitwise addition of  N  and  -N  gives 0
                     if you ignore the carry out of the MSB.
                     Positive integers still have MSB = 0, and 
                     negative integers have MSB=1.
                     Only one representation for zero. 

 Negating an integer is always done using the operation of bitwise
 complementation, i.e. reversing the value of each bit: 

   0  --->  1
   1  --->  0

 The only integer representation used in modern computers is two's
 complement (One's complement was used in the classic CDC machines).
 Two's complement allows the same CPU circuitry to perform addition 
 and subtraction, subtraction is just addition of the negated number.

 See Appendix A for a method to diagnose the type of integer arithmetic
 on your computer.

 Two other number systems that are not extensions of the 'natural' 
 binary representation of positive integers, i.e. they give other 
 values to the positive integers are offset binary and BCD.

   OFFSET BINARY     Rarely used method, the value assigned to a bit
                     pattern is the 'natural value' minus the bit
                     pattern 100...0.
                     Forms an 'ascending' series from the negative to
                     the positive numbers.
                     Equals two's complement but with MSB complemented.
                     Only one representation for zero. 

   BCD               A family of coding systems, all of them generated
                     by taking the decimal representation and coding
                     each decimal digit (and the sign) with 4 bits.


 The following table illustrates the representation methods with
 4 bits bit patterns: 

              Sign-       One's        two's        Offset  
    Integer   magnitude   complement   complement   binary  
    -------   ---------   ----------   ----------   ------  
      +7        0111        0111         0111        1111   
      +6        0110        0110         0110        1110   
      +5        0101        0101         0101        1101   
      +4        0100        0100         0100        1100   
      +3        0011        0011         0011        1011   
      +2        0010        0010         0010        1010   
      +1        0001        0001         0001        1001   
       0        0000        0000         0000        1000   
      -1        1001        1110         1111        0111   
      -2        1010        1101         1110        0110   
      -3        1011        1100         1101        0101   
      -4        1100        1011         1100        0100   
      -5        1101        1010         1011        0011   
      -6        1110        1001         1010        0010   
      -7        1111        1000         1001        0001   
      -8        ----        ----         1000        0000   
     (-0)       1000        1111         ----        ----   
                          

 The following table shows the three common BCD coding systems
 (BCD 8421 is known as just BCD):

      Pattern    BCD 8421   Excess-3   BCD 2421
      --------   --------   --------   --------
       1111                               9
       1110                               8
       1101                               7
       1100                    9          6
       1011                    8          5
       1010                    7
       1001         9          6
       1000         8          5
       0111         7          4
       0110         6          3
       0101         5          2         
       0100         4          1          4
       0011         3          0          3
       0010         2                     2
       0001         1                     1
       0000         0                     0


 BCD arithmetic on strings is really a kind of multiple precision 
 arithmetic (bignums). Old computers implemented BCD in hardware, 
 but it is inefficient compared with integers and reals.

 Excess-3 and BCD 2421 were devised so that bitwise complementation
 will give the 9's complement (the radix 2 analog of 1's complement) 
 of the decimal number, making hardware implementation require more 
 simple circuitry.


 Using integers in place of floating-point numbers
 -------------------------------------------------
 Integers are sometimes called fixed-point numbers because they can
 be viewed as floats with radix point after the least significant 
 digit, and zero fractional digits:

      1      1.000...
     10     10.000...
    100    100.000...

 This strange representation hints at a possible use of integers as
 a replacement for floats. Instead of a float X with p digits decimal 
 mantissa, we can use an integer N: 

    N = INT(X * (10**p))     (Float to integer transformation)

    X = N / (10**p)          (Recovering the float from the integer)


 Addition is simple, you just add the integers.

    X1 + X2 = N1 / (10**p)  +  N2 / (10**p) = (N1 + N2) / (10**p)


 Multiplication is more tricky:

    X1 * X2 = [N1 / (10**p)] * [N2 / (10**p)] 

            = (N1 * N2) / [(10**p)**2]

            = [(N1 * N2) / (10**p)] / (10**p)

 Division by an extra (10**p) factor is needed to get the right answer.

 A common INTEGER type is the INTEGER*4 which has range: 

    [-2,147,483,648 : 2,147,483,647]

 that means that with a 3 digits decimal mantissa you will get only
 the range: 

    [-2,147,483.648 : 2,147,483.647]

 The advantage of using integers instead of floats is that roundoff
 errors are eliminated on addition and subtraction (problematic 
 operations with floats). Radix conversions between the internal
 binary representation and external decimal are also errorless.

 Integer operations takes about the same CPU time as the corresponding 
 float operations.


 Unsigned integers
 -----------------
 If you work with quantities that are always positive, and even 
 intermediary and temporary results are positive, half of the integer
 range is 'wasted'. However, unsigned integers are awkward to emulate 
 with signed integer arithmetic(?).

 You may get the output of a measuring device in a file containing 
 unsigned integers, or get a file created by a program written in
 a language that supports unsigned integers, e.g. C. 


 Comparing unsigned integers
 ---------------------------
 Unsigned integers can be compared with a small routine that uses the 
 ordinary FORTRAN comparison operators:

      LOGICAL FUNCTION UGE(I, J)
C     ------------------------------------------------------------------
      INTEGER   I, J
C     ------------------------------------------------------------------
      IF (I .GE. 0) THEN
        IF (J .LT. 0) THEN
          UGE = .FALSE.
          RETURN
        ENDIF
      ELSE
        IF (J .GE. 0) THEN
          UGE = .TRUE.
          RETURN
        ENDIF
      ENDIF
C     ------------------------------------------------------------------
      IF (I .GE. J) THEN
        UGE = .TRUE.
      ELSE
        UGE = .FALSE.
      ENDIF
C     ------------------------------------------------------------------
      RETURN
      END

 This little monster can be further optimized ...
 

Return to contents page