Modula-3: Arithmetic operations

## Arithmetic operations

The basic arithmetic operations are built into the language; additional operations are provided by the required floating-point interfaces.

To test or set the implementation's behavior for overflow, underflow, rounding, and division by zero, see the required interface `FloatMode`. Modula-3 arithmetic was designed to support the IEEE floating-point standard, but not to require it.

To perform arithmetic operations modulo the word size, programs should use the routines in the required interface `Word`.

Implementations must not rearrange the computation of expressions in a way that could affect the result. For example, `(x+y)+z` generally cannot be computed as `x+(y+z)`, since addition is not associative either for bounded integers or for floating-point values.

        prefix    +  (x: INTEGER)    : INTEGER
                  +  (x: Float)      : Float

         infix    +  (x,y: INTEGER)  : INTEGER
                     (x,y: Float)    : Float
                     (x,y: Set)      : Set

As a prefix operator, `+x` returns `x`. As an infix operator on numeric arguments, `+` denotes addition. On sets, `+` denotes set union. That is, `e IN (x + y)` if and only if `(e IN x) OR (e IN y)`. The types of `x` and `y` must be the same, and the result is the same type as both. In unsafe modules, `+` is extended to `ADDRESS`.

        prefix    -  (x: INTEGER)    : INTEGER
                     (x: Float)      : Float

         infix    -  (x,y: INTEGER)  : INTEGER
                     (x,y: Float)    : Float
                     (x,y: Set)      : Set

As a prefix operator, `-x` is the negative of `x`. As an infix operator on numeric arguments, `-` denotes subtraction. On sets, `-` denotes set difference. That is, `e IN (x - y)` if and only if `(e IN x) AND NOT (e IN y)`. The types of `x` and `y` must be the same, and the result is the same type as both. In unsafe modules, `-` is extended to `ADDRESS`.

        infix     *  (x,y: INTEGER)  : INTEGER
                     (x,y: Float)    : Float
                     (x,y: Set)      : Set

On numeric arguments, `*` denotes multiplication. On sets, `*` denotes intersection. That is, `e IN (x * y)` if and only if `(e IN x) AND (e IN y)`. The types of `x` and `y` must be the same, and the result is the same type as both.

        infix     /  (x,y: Float)    : Float
                     (x,y: Set)      : Set

On reals, `/` denotes division. On sets, `/` denotes symmetric difference. That is, `e IN (x / y)` if and only if `(e IN x) # (e IN y)`. The types of `x` and `y` must be the same, and the result is the same type as both.

        infix    DIV (x,y: INTEGER) : INTEGER
        infix    MOD (x,y: INTEGER) : INTEGER
                 MOD (x, y: Float)  : Float

The value `x DIV y` is the floor of the quotient of `x` and `y`; that is, the maximum integer not exceeding the real number `z` such that `z * y = x`. For integers `x` and `y`, the value of `x MOD y` is defined to be `x - y * (x DIV y)`.

This means that for positive `y`, the value of `x MOD y` lies in the interval `[0 .. y-1]`, regardless of the sign of `x`. For negative `y`, the value of `x MOD y` lies in the interval `[y+1 .. 0]`, regardless of the sign of `x`.

If `x` and `y` are floats, the value of `x MOD y` is `x - y * FLOOR(x / y)`. This may be computed as a Modula-3 expression, or by a method that avoids overflow if `x` is much greater than `y`. The types of `x` and `y` must be the same, and the result is the same type as both.

                 ABS (x: INTEGER) : INTEGER
                     (x: Float)   : Float

`ABS(x)` is the absolute value of `x`. If `x` is a float, the type of `ABS(x)` is the same as the type of `x`.

               FLOAT (x: INTEGER; T: Type := REAL): T
                     (x: Float;   T: Type := REAL): T

`FLOAT(x, T)` is a floating-point value of type `T` that is equal to or very near `x`. The type `T` must be a floating-point type; it defaults to `REAL`. The exact semantics depend on the thread's current rounding mode, as defined in the required interface `FloatMode`.

               FLOOR   (x: Float) : INTEGER

               CEILING (x: Float) : INTEGER

`FLOOR(x)` is the greatest integer not exceeding `x`. `CEILING(x)` is the least integer not less than `x`.

               ROUND (r: Float)   : INTEGER

               TRUNC (r: Float)   : INTEGER

`ROUND(r)` is the nearest integer to `r`; ties are broken according to the constant `RoundDefault` in the required interface `FloatMode`. `TRUNC(r)` rounds `r` toward zero; it equals `FLOOR(r)` for positive `r` and `CEILING(r)` for negative `r`.

           MAX, MIN (x,y: Ordinal) : Ordinal
                    (x,y: Float)   : Float

`MAX` returns the greater of the two values `x` and `y`; `MIN` returns the lesser. If `x` and `y` are ordinals, they must have the same base type, which is the type of the result. If `x` and `y` are floats, they must have the same type, and the result is the same type as both.

    Last modified on Wed Apr  3 09:39:13 PST 1996 by heydon
         modified on Mon Apr 18 14:00:35 PDT 1994 by kalsow