### Integers as an abstract data type

The values of the integer data type are simply whole numbers, zero, positive, and negative. They go on forever in both the positive and negative directions -- there is no greatest or least integer.

Since there are infinitely many integers, it is impossible to perform a separate act of naming for each one. Instead, we rely on a system of numeration -- a set of rules for constructing a name for any given number from its value. We'll use the standard decimal system of numeration, with an explicit sign for negative integers.

The following operations belong to my proposed interface for the integer data type. First, the basic arithmetic operations:

negate
Input: `negand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: The sum of `negand` and `result` is 0.

absolute-value
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the magnitude of `operand`, that is, its distance (in either direction) from 0.

Inputs: `augend` and `addend`, both integers.
Output: `sum`, an integer.
Preconditions: none.
Postcondition: `sum` is the sum of `augend` and `addend`.

subtract
Inputs: `minuend` and `subtrahend`, both integers.
Output: `difference`, an integer.
Preconditions: none.
Postcondition: `minuend` is the sum of `difference` and `subtrahend`.

multiply
Inputs: `multiplicand` and `multiplier`, both integers.
Output: `product`, an integer.
Preconditions: none.
Postcondition: `product` is the product of `multiplicand` and `multiplier`.

divide
Inputs: `dividend` and `divisor`, both integers.
Outputs: `quotient` and `remainder`, both integers.
Precondition: `divisor` is not 0.
Postconditions: `dividend` is the sum of `remainder` and the product of `quotient` and `divisor`. The magnitude of `remainder` is less than the magnitude of `divisor`. If `remainder` is not 0, its sign is the same as the sign of `dividend`.

quotient
Inputs: `dividend` and `divisor`, both integers.
Output: `result`, an integer.
Precondition: `divisor` is not 0.
Postcondition: `result` is the quotient resulting from the division of `dividend` by `divisor`. (In other words, it is the first output when divide is applied to `dividend` and `divisor`.)

remainder
Inputs: `dividend` and `divisor`, both integers.
Output: `result`, an integer.
Precondition: `divisor` is not 0.
Postcondition: `result` is the remainder resulting from the division of `dividend` by `divisor`. (In other words, it is the second output when divide is applied to `dividend` and `divisor`.)

modulo
Inputs: `moduland` and `modulus`, both integers.
Output: `result`, an integer.
Precondition: `modulus` is not 0.
Postconditions: The difference between `moduland` and `result` is an exact multiple of `modulus`. The magnitude of `result` is less than the magnitude of `modulus`. If `result` is not 0, its sign is the same as the sign of `modulus`.

raise
Inputs: `base`, an integer, and `exponent`, a natural number.
Output: `power`, an integer.
Preconditions: none.
Postconditions: `power` is the result of raising `base` to the power of `exponent`. If both `base` and `exponent` are 0, `power` is 1.

The next five operations are special cases of the preceding ones that occur frequently enough to be treated separately:

successor
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the integer immediately following `operand`. (In other words, `result` is the sum of `operand` and 1.)

predecessor
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `operand` is the integer immediately following `result`. (In other words, `oeprand` is the sum of `result` and 1.)

twice
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the product of `operand` and 2.

square
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the result of raising `operand` to the power 2.

cube
Input: `operand`, an integer.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the result of raising `operand` to the power 3.

Next, the comparison operations:

equal
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if the operands are the same integer, false if they are different integers.

unequal
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if the operands are different integers, false if they are the same integer.

less
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `left-operand` is less than `right-operand`, false if it is greater than `right-operand` or if both operands are the same integer.

less-or-equal
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `left-operand` is less than `right-operand` or if both operands are the same integer, false if `left-operand` is greater than `right-operand`.

greater
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `left-operand` is greater than `right-operand`, false if it is less than `right-operand` or if both operands are the same integer.

greater-or-equal
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `left-operand` is greater than `right-operand` or if both operands are the same integer, false if `left-operand` is less than `right-operand`.

major
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the greater of the operands.

minor
Inputs: `left-operand` and `right-operand`, both integers.
Output: `result`, an integer.
Preconditions: none.
Postcondition: `result` is the lesser of the operands.

Again, some special cases of the preceding predicates are worth defining:

zero
Input: `operand`, an integer.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `operand` is 0, false if it is any other integer.

negative
Input: `operand`, an integer.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `operand` is less than 0, false if it is greater or if it is 0.

positive
Input: `operand`, an integer.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `operand` is greater than 0, false if it is less or if it is 0.

Various tests for attributes of integers:

multiple
Inputs: `candidate` and `unit`, both integers.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `candidate` is an exact multiple of `unit`, false otherwise. (Note that 0 is an exact multiple of every integer, including itself.)

even
Input: `operand`, an integer.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is true if `operand` is an exact multiple of 2, false if it is not.

odd
Input: `operand`, an integer.
Output: `result`, a Boolean.
Preconditions: none.
Postcondition: `result` is false if `operand` is an exact multiple of 2, true if it is not.

Finally, the input and output operations:

Input: `source`, a data source (e.g., a file, the keyboard, a device).
Outputs: `legend`, an integer, and `success`, a Boolean.
Preconditions: none.
Postcondition: Either some representation of an integer value has been extracted from `source` and `legend` is that integer value, or an input error of some kind has occurred and `success` is false.

write
Inputs: `target`, a data sink (e.g., a file, a window, a device), and `scribend`, an integer.
Outputs: none.
Preconditions: none.
Postcondition: A representation of `scribend` has been appended to `target`.

### Integers in standard Pascal

Values of the standard Pascal `Integer` type are essentially always represented as word-length data, and therefore constitute a finite, fixed range of integers; integers outside of this range are not representable. In effect, preconditions are added to all of the operations, asserting that the inputs and outputs of the operation all lie within the specified range. Since it is often difficult or impossible to ascertain the truth of these preconditions before performing the operations, this feature of standard Pascal is a common source of programming errors.

In a subsequent handout, we'll develop a way of avoiding this limitation, defining a different integer type that includes arbitrarily large values. In the meantime, we'll try to live within the confines of the standard `Integer` type, remembering to stay within the permitted range.

In Standard Pascal, decimal numerals are used as names for values of the `Integer` type. It also provides an alternative name, `MaxInt`, for the largest value of the `Integer` data type. It guarantees that all integers in the range from `-MaxInt` to `MaxInt`, inclusive, are representable. (In many implementations, such as HP Pascal, the integer `-MaxInt - 1` is also representable, but the standard does not guarantee this.)

Of the operations listed above, standard Pascal provides about half:

• negate (as the unary minus operator, `-`)
• absolute-value (as the `Abs` function)
• add (as the `+` operator)
• subtract (as the binary minus operator, `-`)
• multiply (as the `*` operator)
• quotient (as the `div` operator)
• successor (as the `Succ` function)
• predecessor (as the `Pred` function)
• square (as the `Sqr` function)
• equal (as the relational operator `=`)
• unequal (as `<>`)
• less (as `<`)
• less-or-equal (as `<=`)
• greater (as `>`)
• greater-or-equal (as `>=`)
• odd (as the `Odd` function)
• write (as the `Write` procedure)
It comes close to providing modulo (as the `mod` operator), but adds the precondition that `modulus` be positive; and it provides a version of read that crashes when the input is not to its liking, rather than setting a `success` flag.

Standard Pascal also provides an identity operation on integers -- that is, a function (`Ord`) that takes any integer as argument and returns the same integer.

### Supplying the missing operations

Once again, it is straightforward to supplement the built-in operations in Pascal with programmer-defined functions and procedures to complete the implementation of the abstract data type:
```{ Even in implementations, such as HP Pascal, where -MaxInt - 1 is a
representable integer, it usually has to receive exceptional treatment in
arithmetic operations, since its negative is not representable.  (This
implies, for instance, that one cannot take its absolute value, divide it
by -1, etc.)  In these procedures, I've dealt with the problem by writing
assertions that filter out this value whenever it would interfere with
the usual algorithm.

The identifier MinInt is predefined (as a non-standard extension to the
language) in HP Pascal. }

procedure Divide (Dividend: Integer; Divisor: Integer;
var Quotient: Integer; var Remainder: Integer);
begin
{ Assert (Divisor <> 0); }
{ Assert ((Dividend <> MinInt) and (Divisor <> MinInt); }
Quotient := Dividend div Divisor;
Remainder := Dividend - (Quotient * Divisor)
end;

function Remainder (Dividend: Integer; Divisor: Integer): Integer;
var
UnsignedResult: Integer;
begin
{ Assert (Divisor <> 0); }
{ Assert ((Dividend <> MinInt) and (Divisor <> MinInt)); }
UnsignedResult := Abs (Dividend) mod Abs (Divisor);
if Dividend < 0 then
Remainder := -UnsignedResult
else
Remainder := UnsignedResult
end;

function Modulo (Moduland: Integer; Modulus: Integer): Integer;
var
UnsignedResult: Integer;
begin
{ Assert (Modulus <> 0); }
{ Assert ((Moduland <> MinInt) and (Modulus <> MinInt)); }
UnsignedResult := Moduland mod Abs (Modulus);
if (Modulus < 0) and (UnsignedResult <> 0) then
Modulo := UnsignedResult + Modulus
else
Modulo := UnsignedResult
end;

{ The Raise function presupposes that the result of the exponentiation
operation is representable as an integer, but does not confirm this
presupposition.

The algorithm used in this function begins with three arithmetic facts:

k^0 = 1

k^(2n) = (k^n)^2

k^(2n + 1) = k * (k^n)^2

Thus, if Exponent is 0, the function can immediately return 1; if it is
greater than 0 and even, the function can raise the same base to a
power half as large, then square the result; if it is greater than 0
and odd, the function can perform the same squaring operation, then
multiply the result by the base.

The recursion must terminate, since Exponent is initially non-negative
and is strictly smaller on each recursive call, while never becoming
negative.  It must therefore eventually reach 0, at which point the
recursion stops. }

function Raise (Base: Integer; Exponent: Integer): Integer;
var
Square: Integer;
begin
{ Assert (0 <= Exponent); }
if Exponent = 0 then
Raise := 1
else begin
Square := Sqr (Raise (Base, Exponent div 2));
if Odd (Exponent) then
Raise := Square * Base
else
Raise := Square
end
end;

{ The Twice function presupposes that the result of the doubling
operation is representable as an integer. }

function Twice (Operand: Integer): Integer;
begin
{ Assert ((MinInt div 2 <= Operand) and (Operand <= MaxInt div 2)); }
Twice := 2 * Operand
end;

{ The Cube function presupposes that its result is representable as an
integer. }

function Cube (Operand: Integer): Integer;
const
IntegerCubeRootOfMinInt = -1290;
IntegerCubeRootOfMaxInt = 1290;
begin
{ Assert ((IntegerCubeRootOfMinInt <= Operand) and
(Operand <= IntegerCubeRootOfMaxInt)); }
Cube := Operand * Operand * Operand
end;

function Major (LeftOperand, RightOperand: Integer): Integer;
begin
if LeftOperand < RightOperand then
Major := RightOperand
else
Major := LeftOperand
end;

function Minor (LeftOperand, RightOperand: Integer): Integer;
begin
if LeftOperand < RightOperand then
Minor := LeftOperand
else
Minor := RightOperand
end;

function Zero (Operand: Integer): Boolean;
begin
Zero := (Operand = 0)
end;

function Negative (Operand: Integer): Boolean;
begin
Negative := (Operand < 0)
end;

function Positive (Operand: Integer): Boolean;
begin
Positive := (0 < Operand)
end;

function Multiple (Candidate: Integer; Unit: Integer): Boolean;
begin
{ Assert (Unit <> MinInt); }
if Unit = 0 then
Multiple := (Candidate = 0)
else
Multiple := (Candidate mod Abs (Unit) = 0)
end;

function Even (Operand: Integer): Boolean;
begin
Even := not Odd (Operand)
end;
```

This document is available on the World Wide Web as

```http://www.math.grin.edu/~stone/courses/fundamentals/integers.html
```

created July 24, 1996
last revised August 21, 1996