New integer subtypes declared by imposing constraints on INTEGER inherit these operations: relational operators deliver a result of type BOOLEAN; all others deliver a result of the same type as the operands. Both operands of the binary operators must have the same type, excepting exponentiation, for which the right operand type is always INTEGER. If system-defined integer types such as LONG_INTEGER are implemented, then overloadings of the arithmetic and relational operators are defined for these types in an analogous manner; and similarly for SHORT_INTEGER, if implemented.
The user can define an integer type by specifying the range to be covered, for example
type PAGE_NUM is range 1 .. 2000; type MY_INTEGER is range -100_000 .. 100_000;
in which case the implementation will use whichever predefined type just encompasses this range. Thus MY_INTEGER would be implemented as (a subtype of a type derived from) LONG_INTEGER on a typical 16-bit minicomputer, but as INTEGER on a machine with larger word length. Portability of the program is thus assured, in this respect.
Furthermore, a range constraint can be applied to a type to give a subtype. The subtype has all the operations of the base type, but the value of any variable of the subtype must always be within the range of the subtype; in general this is checked before assigning a value to the variable. One would expect compilers to represent subtypes in the same way as types, but in special cases the compiler may be able to optimize the representation by utilizing the range constraint. Thus the subtype
subtype SIGN is INTEGER range -1 .. 1;
contains only three values, so that each value could be stored using one byte, or even two bits.
The operations /, mod, and rem require explanation. There is no universal agreement on the semantics of these operations for negative operand values. Because different machines perform these operations differently, it is tempting not to define them for negative values. This is the approach taken in the axiomatic definition of Pascal [HW 73]. The semantics chosen in the Ada language corresponds to division with truncation toward zero (so (-3)/2 = -1). This has the advantage that it preserves the identity:
-(A/B) = (-A)/B = A/(-B)
The operations / and rem are related by
A = (A/B)*B + (A rem B)
so that rem provides the remainder on division. As a consequence the sign of the result of the rem operation is therefore the same as the sign of A (hence A rem 10 can be negative). Also the absolute value of the result of the rem operation is less than the absolute value of B.
The operation mod on the other hand is defined so that (A mod B) always has the same sign as B and its absolute value is less than the absolute value of B; subject to these conditions it must differ from A by an integer multiple of B, that is, for some integer value N it satisfies the relation
A = B*N + (A mod B)
Integer exponentiation is defined only for nonnegative exponents. Hence, I**(-1) will raise CONSTRAINT_ERROR as the exponent is not positive. The operation is defined as repeated multiplication of the left hand operand. The number of multiplications is one less than the exponent value, so I**2 = I*I and I**4 = I*I*I*I.
The predefined operator abs yields the absolute value of its operand, and is defined for all numeric types.