THE CLASS "ENVIRONMENT"

The purpose of the environmental class is to encapsulate all constants, procedures and classes which are accessible to all source modules. It contains procedures for mathematical functions, text generation, random drawing, etc.

The general structure of ENVIRONMENT is

classENVIRONMENT;begincharacterCURRENTLOWTEN, CURRENTDECIMALMARK; Basic operations ........................................ 9.1 Procedures mod, rem, abs, sign, entier, addepsilon, subepsilon. Text utilities .......................................... 9.2 Procedures copy, blanks, char, isochar, rank, isorank, digit, letter, lowten, decimalmark, upcase, lowcase. Scheduling .............................................. 9.3 Procedures call (7.3.2), resume (7.3.3). Mathematical functions .................................. 9.4 Procedures sqrt, sin, cos, tan, cotan, arcsin, arccos, arctan, arctan2, sinh, cosh, tanh, ln, log10, exp. Extremum functions ...................................... 9.5 Procedures max, min. Environmental enquiries ................................. 9.6 Procedure sourceline. Constants maxrank, maxint, minint, maxreal, minreal, maxlongreal, minlongreal, simulaid. Error control ........................................... 9.7 Procedure error. Array quantities ........................................ 9.8 Procedures upperbound, lowerbound. Random drawing .......................................... 9.9 Procedures draw, randint, uniform, normal, negexp, Poisson, Erlang, discrete, linear, histd. Calendar and timing utilities ........................... 9.10 Procedures datetime, cputime, clocktime. Miscellaneous utilities ................................. 9.11 Procedure histo. Standard system classes ................................. 9.12 Classes simset (ch. 11), simulation (ch. 12). CURRENTDECIMALMARK := '.'; CURRENTLOWTEN := '&'endENVIRONMENT;

MODintegerproceduremod(i,j);integeri,j;beginintegerres; res := i - (i//j)*j; mod :=ifres = 0then0elseifsign(res) <> sign(j)thenres+jelseresendmod; The result is the mathematical modulo value of the parameters. REMintegerprocedurerem(i,j);integeri,j; rem := i - (i//j)*j; The result is the remainder of an integer division. ABS <type of e>procedureabs(e);e; abs := ife >= 0theneelse-e; The result is the absolute value of the parameter. SIGNintegerproceduresign(e);e; sign := ife > 0then1elseife < 0then-1else0; The result is zero if the parameter is zero, one if the parameter is positive, and minus one otherwise. ENTIERintegerprocedureentier(r); <real-type> r;beginintegerj; j := r; ! implied conversion of "r" to integer ; entier:=ifj > r ! implied conversion of "j" to real ;thenj-1elsejendentier; The result is the integer "floor" of a real type item, the value always being less than or equal to the parameter. Thus, entier(1.8) returns the value 1, while entier(-1.8) returns -2. ADDEPSILON <type of e>procedureaddepsilon(e); <real-type> e; addepsilon := e + ... ; ! see below; SUBEPSILON <type of e>proceduresubepsilon(e); <real-type> e; subepsilon := e - ... ; ! see below; The result type is that of the parameter. The result is the value of the parameter incremented (addepsilon) or decremented (subepsilon) by the smallest positive value, such that the result is not equal to the parameter within the precision of the implementation. Thus, for all positive values of "eps", E-eps <= subepsilon(E) < E < addepsilon(E) <= E+eps

COPY See 8.3. BLANKS See 8.3. CHARcharacterprocedurechar(i);integeri; char := ... ; The result is the character obtained by converting the parameter according to the implementation-defined coding of characters. The parameter must be in the range 0..maxrank. ISOCHARcharacterprocedureisochar(i);integeri; isochar := ... ; The result is the character obtained by converting the parameter according to the ISO 2022 standard character code. The parameter must be in the range 0..255. RANKintegerprocedurerank(c);characterc; rank := ... ; The result is the integer obtained by converting the parameter according to the implementation-defined character code. ISORANKintegerprocedureisorank(c);characterc; isorank := ... ; The result is the integer obtained by converting the parameter according to the ISO 2022 standard character code. DIGITBooleanproceduredigit(c);characterc; digit := ... ; The result istrueif the parameter is a decimal digit. LETTERBooleanprocedureletter(c);characterc; letter := ... ; The result is true if the parameter is a letter of the English alphabet ('a' ... 'z', 'A' ... 'Z'). LOWTENcharacterprocedurelowten(c);characterc;if... ! c is illegal as lowten;thenerror("..." ! Lowten error ;)elsebeginlowten:= CURRENTLOWTEN; CURRENTLOWTEN:= cendlowten; Changes the value of the current lowten character to that of the parameter. The previous value is returned. Illegal parameters are digits, plus ("+"), minus ("-"), dot ("."), comma (","), control characters (i.e. ISO code<32), DEL (ISO code 127), and all characters with ISO code greater than 127. DECIMALMARKcharacterproceduredecimalmark(c);characterc;ifc <> '.'andthenc <> ','thenerror("..." ! Decimalmark error ;)elsebegindecimalmark:= CURRENTDECIMALMARK; CURRENTDECIMALMARK:= cenddecimalmark; Changes the value of the decimal point character used by the text (de)editing procedures (cf. 8.7 and 8.8). The previous value is returned. The only legal parameter values are dot and comma. UPCASEtextprocedureupcase(t);textt;begint.setpos(1); upcase:- t; ...end; Convert the letters in the text parameter to their upper case representation. Only letters of the English alphabet are converted. The result is a reference to the parameter. LOWCASEtextprocedurelowcase(t);textt;begint.setpos(1); lowcase:- t; ...end; Convert the letters in the text parameter to their lower case representation. Only letters of the English alphabet are converted. The result is a reference to the parameter.

CALL See 7.3.2. RESUME See 7.3.3.

In addition the procedure "detach" (7.3.1) is an attribute of any class.

These procedures return **long** **real** results whenever a parameter is of this
type. Otherwise a **real** type result is returned (cf. 3.3.1).

All procedures return real type approximations to the associated mathematical functions. Their exact definitions (concerning precision, allowed parameter values etc.) are implementation-defined. The procedures return best possible approximations to the exact mathematical results.

The trigonometric functions deal with angles expressed in radians.

SQRT <real-type>proceduresqrt(r); <real-type> r; SIN <real-type>proceduresin(r); <real-type> r; COS <real-type>procedurecos(r); <real-type> r; TAN <real-type>proceduretan(r); <real-type> r; COTAN <real-type>procedurecotan(r); <real-type> r; ARCSIN <real-type>procedurearcsin(r); <real-type> r; ARCCOS <real-type>procedurearccos(r); <real-type> r; ARCTAN <real-type>procedurearctan(r); <real-type> r; The result is in the range (0,pi/2) for non-negative parameters and in the range (-pi/2,0) for negative parameters. ARCTAN2 <real-type>procedurearctan2(y,x); <real-type> y,x; The result is in the range(-pi,pi) and a negative value is returned whenever y is negative. Positive y values always result in a positive result, while a zero value returns zero if x is positive and pi if x is negative. If both y and x are zero, a runtime error occurs. SINH <real-type>proceduresinh(r); <real-type> r; COSH <real-type>procedurecosh(r); <real-type> r; TANH <real-type>proceduretanh(r); <real-type> r; LN <real-type>procedureln(r); <real-type> r; LOG10 <real-type>procedurelog10(r); <real-type> r; EXP <real-type>procedureexp(r); <real-type> r;

SOURCELINEintegerproceduresourceline; The value indicates the line on which the procedure call occurs. The interpretation of this number is implementation-defined. MAXLONGREALlongrealmaxlongreal = ... , MINLONGREAL minlongreal = ... ; MAXREALrealmaxreal = ... , MINREAL minreal = ... ; MAXRANKintegermaxrank = ... , !the largest legal argument to char; MAXINT maxint = ... , MININT minint = ... ; These constants define some of the implementation characteristics. The "max..." ("min...") constants have the largest (smallest) values possible for their type. SIMULAIDtextsimulaid = ... ; ! See below ;

The value of "simulaid" is an implementation defined string of the following general format:

<simid>!!!<siteid>!!!<OS>!!!<CPU>!!!<user>!!!<job>!!!<acc>!!!<prog> <simid>: Identification of the SIMULA system (name, version etc.) <siteid>: Identification of the installation (e.g. organisation name) <OS>: Operating system identification (name, version, etc.) <CPU>: Host system identification (manufacturer, name, number, etc.) <user>: User identification <job>: Job identification (session number) <acc>: Account identification <prog>: Identification of the executing task or program

ERRORprocedureerror(t);textt;begin... display text "t" and stop program...enderror;

The procedure "error" stops the execution of the program as if a runtime error has occurred and presents the contents of the text parameter on the diagnostic channel (normally the controlling terminal).

LOWERBOUNDintegerprocedurelowerbound(a,i); <type>arraya;integeri; UPPERBOUNDintegerprocedureupperbound(a,i); <type>arraya;integeri;

The procedure "lowerbound" ("upperbound") returns the lower (upper) bound of the dimension of the given array corresponding to the given index. The first dimension has index one, the next two, etc. An index less than one or greater than the number of dimensions of the given array constitutes a run time error.

All random drawing procedures of SIMULA are based on the technique of obtaining "basic drawings" from the uniform distribution in the interval <0,1>.

A basic drawing replaces the value of a specified **integer** variable, say U, by
a new value according to an implementation-defined algorithm.

As an example, the following algorithm may be suitable for binary computers:

U(i+1) = remainder ((U(i) * 5**(2*p+1)) // 2**n)where U(i) is the i'th value of U, n is an integer related to the size of a computer word and p is a positive integer. It can be proved that, if U(0) is a positive odd integer, the same is true for all U(i) and the sequence U(0), U(1), U(2), ... is cyclic with period 2**n-2. (The last two bits of U remain constant, while the other n-2 take on all possible combinations). Thus there are two sequences - one in the range (1:2**n-3) and the other in (3:2**n-1).

It is a property of this algorithm that any successor to a stream number U(i), e.g. U(i+m), can be computed using modular arithmetic in log2(m) steps.

The real numbers u(i) = U(i) * 2**(-n) are fractions in the range <0,1>. The sequence u(1), u(2), ... is called a "stream" of pseudo- random numbers, and u(i) (i = l,2, ...) is the result of the i'th basic drawing in the stream U. A stream is completely determined by the initial value U(0) of the corresponding integer variable. Nevertheless, it is a "good approximation" to a sequence of truly random drawings.

By reversing the sign of the non-zero initial value U(0) of a stream variable, the antithetic drawings 1-u(1), 1-u(2), ... should be obtained. In certain situations it can be proved that means obtained from samples based on antithetic drawings have a smaller variance than those obtained from uncorrelated streams. This can be used to reduce the sample size required to obtain reliable estimates.

The following procedures all perform a random drawing of some kind. "Normal",
"draw", "randint", "uniform", "negexp", "discrete", "linear" and "histd" always
perform the operation by means of one single basic drawing, i.e. the procedure
has the side effect of advancing the specified stream by one step. The
necessary type conversions are effected for the actual parameters, with the
exception of the last one. The latter must always be an **integer** variable
specifying a pseudo-random number stream. Note, that it must not be a procedure
parameter transferred by **name**.

DRAWBooleanproceduredraw (a,U);nameU;longreala;integerU; The value istruewith the probability a,falsewith the probability 1 - a. It is alwaystrueif a >= 1 and alwaysfalseif a <= 0. RANDINTintegerprocedurerandint (a,b,U);nameU;integera,b,U; The value is one of the integers a, a+1, ..., b-1, b with equal probability. If b < a, the call constitutes an error. UNIFORMlongrealprocedureuniform (a,b,U);nameU;longreala,b;integerU; The value is uniformly distributed in the interval a <= u < b. If b < a, the call constitutes an error. NORMALlongrealprocedurenormal (a,b,U);nameU;longreala,b;integerU; The value is normally distributed with mean a and standard deviation b. An approximation formula may be used for the normal distribution function. NEGEXPlongrealprocedurenegexp (a,U);nameU;longreala;integerU; The value is a drawing from the negative exponential distribution with mean 1/a, defined by -ln(u)/a, where u is a basic drawing. This is the same as a random "waiting time" in a Poisson distributed arrival pattern with expected number of arrivals per time unit equal to a. If a is non-positive, a runtime error occurs. POISSONintegerprocedurePoisson (a,U);nameU;longreala;integerU; The value is a drawing from the Poisson distribution with parameter a. It is obtained by n+1 basic drawings, u(i), where n is the function value. n is defined as the smallest non-negative integer for which u(0) * u(1) * ... * u(n) < e**(-a) The validity of the formula follows from the equivalent condition -ln(u(0)) - ln(u(1)) - ... - ln(u(n)) > 1 where the left hand side is seen to be a sum of "waiting times" drawn from the corresponding negative exponential distribution. When the parameter a is greater than some implementation-defined value, for instance 20.0, the value may be approximated by entier(normal(a,sqrt(a),U) + 0.5) or, when this is negative, by zero. ERLANGlongrealprocedureErlang (a,b,U);nameU;longreala,b;integerU; The value is a drawing from the Erlang distribution with mean 1/a and standard deviation 1/(a*sqrt(b)). It is defined by b basic drawings u(i), if b is an integer value, - ( ln(u(1)) + ln(u(2)) + ... + ln(u(b)) ) / (a*b) and by c+1 basic drawings u(i) otherwise, where c is equal to entier(b), - ( ln(u(1)) + ... + ln(u(c)) + (b-c)*ln(u(c+1)) ) / (a*b) Both a and b must be greater than zero. The last formula represents an approximation. DISCRETEintegerprocedurediscrete (A,U);nameU; <real-type>arrayA;integerU; The one-dimensional array A, augmented by the element 1 to the right, is interpreted as a step function of the subscript, defining a discrete (cumulative) distribution function. The function value satisfies lowerbound(A,1) <= discrete(A,U) <= upperbound(A,1)+1. It is defined as the smallest i such that A(i) > u, where u is a basic drawing and A(upperbound(A,1)+1) = 1. LINEARlongrealprocedurelinear (A,B,U);nameU; <real-type>arrayA,B;integerU; The value is a drawing from a (cumulative) distribution function F, which is obtained by linear interpolation in a non-equidistant table defined by A and B, such that A(i) = F(B(i)). It is assumed that A and B are one-dimensional arrays of the same length, that the first and last elements of A are equal to 0 and 1 respectively and that A(i) >= A(j) and B(i) > B(j) for i>j. If any of these conditions are not satisfied, the effect is implementation-defined. The steps in the function evaluation are: l. draw a uniform <0,1> random number, u. 2. determine the lowest value of i, for which A(i-1) <= u <= A(i) 3. compute D = A(i) - A(i-1) 4. if D = 0: linear = B(i-1) if D <> 0: linear = B(i-1) + (B(i) - B(i-1))*(u-A(i-1))/D HISTDintegerprocedurehistd (A,U);nameU; <real-type>arrayA;integerU; The value is an integer in the range (lsb,usb), where lsb and usb are the lower and upper subscript bounds of the one-dimensional array A. The latter is interpreted as a histogram defining the relative frequencies of the values.

DATETIME:textproceduredatetime; datetime :- Copy("..."); The value is a text frame containing the current date and time in the form YYYY-MM-DD HH:MM:SS.sss.... The number of decimals in the field for seconds is implementation-defined. CPUTIME:longrealprocedurecputime; The value is the number of processor seconds spent by the calling program. CLOCKTIME:longrealprocedureclocktime; The value is the number of seconds since midnight.

HISTO:procedurehisto(A,B,c,d);realarrayA,B;realc,d;

Procedure statement "histo(A,B,c,d)" updates a histogram defined by the one-dimensional arrays A and B according to the observation c with the weight d. A(lba+i) is increased by d, where i is the smallest integer such that c <= B(lbb+i) and lba and lbb are the lower bounds of A and B respectively. If the length of A is not one greater than that of B the effect is implementation-defined. The last element of A corresponds to those observations which are greater than all elements of B.

The standard system classes are "simset", "simulation" and the I/O classes. They are available at any block level of a program (cfr. 5.5.1).

Class "simset" contains facilities for list (set) manipulation, see chapter 11.

Simset **class** "simulation" contains facilities for discrete event simulation,
see chapter 12.

The I/O classes ("file" and its subclasses) are defined in **class** BASICIO,
see chapter 10.