Most of the standard procedures that are built-in to Modula-2 have already arisen in the course of various examples thus far in the text. The purpose of this section is to provide a summary in one place of all the standard procedures, together with a few examples of code utilizing them.

(i) **ABS** (number) returns the "absolute value" of "number".

Theabsolute valueof a number is its distance from zero, without regard to direction. More technically, it is the square root of the square of a number.

Either way one looks at it:

ABS(5) = 5ABS(-10) = 10ABS(2.7) = 2.7ABS(-3.51) = 3.51

The actual parameter type and the result type must either be both INTEGER or both REAL. There is a little magic in this, in that no user-defined procedure can take or return more than one type, even through the built-in function procedure may do so. If one had *firstInt* and *secondInt* of type INTEGER and *firstReal* and *secondReal* of type REAL, the following would be valid:

firstInt :=ABS(secondInt); firstReal :=ABS(secondReal); firstInt :=TRUNC(ABS(secondReal)); firstReal :=FLOAT(ABS(secondInt));

Recall that there is a potential problem with loops that fail to terminate or comparisons that fail to yield equality because a REAL might never be identically equal to zero. ABS allows this to be avoided by writing, say:

REPEATstatement sequence;UNTILABS(realVar) < epsilon; (* set to a small number, say .0000001 *)

The loop terminates when the *realVar* becomes sufficiently close to zero.

(ii) **CHR** (number) returns the character whose associated numerical value is the CARDINAL *number*. This number is sequential number of the character, in the underlying national character set (often ISO/ASCII.)

If one wrote the assignment ch := **CHR** (65) then *ch* would be equal to *A*

(iii) **DEC** (s) and **INC** (s)--subtract or add one (respectively) to the scalar *s*.

(iv) **DEC** (s, number), **INC** (s, number)--subtract *number* or add *number* (respectively) to the scalar *s*.

VARnum :CARDINAL; ch :CHAR;BEGINnum := 1;DEC(num); (* it's now zero *)INC(num, 8); (* now it's eight *) ch := "Z";INC(ch); (* holds next char after "Z" *)INC(num, num-1) (* now it's 15 *) (*INCallows expressions for the increment *)

Care must be taken not to INC or DEC a variable beyond its defined limits. For instance, if *num* were zero, then DEC (*num*) would leave *num* undefined. As noted, the increment or decrement need not be a literal; it can be any expression that evaluates to a number compatible with the type of variable being used. *INC* (*ch*, *b-a*) is allowed, provided *b-a* is a suitable INTEGER. This in turn means that it is correct to INC or DEC by a negative number.

**NOTES**: 1. When there is a choice between x := x + 1 and INC (x), always use the latter, as in most systems the code generated executes more quickly. The same applies to DEC.

2. The two versions each of INC and DEC are the only regular procedures described in this section. The others are all function procedures.

(v) **CAP** (ch) converts the contents of the CHAR variable to uppercase.

If ch, ck are both of type CHAR then:

ch := 'a' (* or, ch := 'A' *) ck :=CAP(ch) would leave ck holding the value 'A'.

This was used to avoid writing:

IF(ch = 'Y')OR(ch = 'y').

WriteString ("Are you sure you want to do this? "); WriteLn; WriteString ("Answer Y or N ===> "); Read (ans);IFCAP(ans) = 'Y'THENExecute (Program)ELSEExecute (User)END;

(vi) **FLOAT** (n) and **LFLOAT** (n) convert any real, integer, or cardinal into the type REAL or LONGREAL, respectively. Thus:

realVar :=FLOAT(5); (* produces 5.0 *) lrealVar :=LFLOAT(realVar); (* produces longreal 5.0 *) lrealVar :=LFLOAT(-10); (* produces -10.0 in longreal format *)

(vii) **ODD** (n) is a BOOLEAN function that returns TRUE if the INTEGER or CARDINAL expression *n* is odd and FALSE if it is even.

VARflag :BOOLEANnumber :CARDINALBEGINnumber := 5; flag :=ODD(number); (* flag is now true *)INC(number); (* flag is still true; it has not been re-evaluated *) flag :=ODD(number); (* flag is now false *)

Here is a section of code that raises the quantity (-1) to the power *exponent* and places the result in the variable *answer*.

PROCEDUREPowerOfOne (theExponent :INTEGER) :INTEGER;BEGINIFODD(exponent)THENRETURN-1ELSERETURN1END;ENDPowerOfOne;

(viii) **MAX** (type) and **MIN** (type) take as a parameter the name of any scalar type (including REAL) and return the maximum and minimum values possible for items of that type (respectively). MAX and MIN are most useful, for example, when applied just before attempting to TRUNC a REAL. Assume that *integerNum* is INTEGER and *realNum* is REAL.

IF(realNum > 0)AND(realNum <FLOAT(MAX(INTEGER)) )THENintegerNum :=TRUNC(realNum)ELSEErrorRoutineEND

(ix) **TRUNC**(num) and **INT**(num) will convert the supplied numeric parameter to a cardinal or integer value, respectively, with truncation as needed. Thus:

TRUNC(ABS(-7.245)); (* produces 7 *)TRUNC(8.1); (* produces 8 *)INT(2.3); (* produces 2 *)INT(-4.78); (* produces -4 *)