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
class ENVIRONMENT; begin character CURRENTLOWTEN, 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 := '&' end ENVIRONMENT;
MOD integer procedure mod(i,j); integer i,j; begin integer res; res := i - (i//j)*j; mod := if res = 0 then 0 else if sign(res) <> sign(j) then res+j else res end mod; The result is the mathematical modulo value of the parameters. REM integer procedure rem(i,j); integer i,j; rem := i - (i//j)*j; The result is the remainder of an integer division. ABS <type of e> procedure abs(e);e; abs := if e >= 0 then e else -e; The result is the absolute value of the parameter. SIGN integer procedure sign(e); e; sign := if e > 0 then 1 else if e < 0 then -1 else 0; The result is zero if the parameter is zero, one if the parameter is positive, and minus one otherwise. ENTIER integer procedure entier(r); <real-type> r; begin integer j; j := r; ! implied conversion of "r" to integer ; entier:= if j > r ! implied conversion of "j" to real ; then j-1 else j end entier; 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> procedure addepsilon(e); <real-type> e; addepsilon := e + ... ; ! see below; SUBEPSILON <type of e> procedure subepsilon(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. CHAR character procedure char(i); integer i; 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. ISOCHAR character procedure isochar(i); integer i; 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. RANK integer procedure rank(c); character c; rank := ... ; The result is the integer obtained by converting the parameter according to the implementation-defined character code. ISORANK integer procedure isorank(c); character c; isorank := ... ; The result is the integer obtained by converting the parameter according to the ISO 2022 standard character code. DIGIT Boolean procedure digit(c); character c; digit := ... ; The result is true if the parameter is a decimal digit. LETTER Boolean procedure letter(c); character c; letter := ... ; The result is true if the parameter is a letter of the English alphabet ('a' ... 'z', 'A' ... 'Z'). LOWTEN character procedure lowten(c); character c; if ... ! c is illegal as lowten; then error("..." ! Lowten error ;) else begin lowten:= CURRENTLOWTEN; CURRENTLOWTEN:= c end lowten; 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. DECIMALMARK character procedure decimalmark(c); character c; if c <> '.' and then c <> ',' then error("..." ! Decimalmark error ;) else begin decimalmark:= CURRENTDECIMALMARK; CURRENTDECIMALMARK:= c end decimalmark; 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. UPCASE text procedure upcase(t); text t; begin t.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. LOWCASE text procedure lowcase(t); text t; begin t.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> procedure sqrt(r); <real-type> r; SIN <real-type> procedure sin(r); <real-type> r; COS <real-type> procedure cos(r); <real-type> r; TAN <real-type> procedure tan(r); <real-type> r; COTAN <real-type> procedure cotan(r); <real-type> r; ARCSIN <real-type> procedure arcsin(r); <real-type> r; ARCCOS <real-type> procedure arccos(r); <real-type> r; ARCTAN <real-type> procedure arctan(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> procedure arctan2(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> procedure sinh(r); <real-type> r; COSH <real-type> procedure cosh(r); <real-type> r; TANH <real-type> procedure tanh(r); <real-type> r; LN <real-type> procedure ln(r); <real-type> r; LOG10 <real-type> procedure log10(r); <real-type> r; EXP <real-type> procedure exp(r); <real-type> r;
SOURCELINE integer procedure sourceline; The value indicates the line on which the procedure call occurs. The interpretation of this number is implementation-defined. MAXLONGREAL long real maxlongreal = ... , MINLONGREAL minlongreal = ... ; MAXREAL real maxreal = ... , MINREAL minreal = ... ; MAXRANK integer maxrank = ... , !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. SIMULAID text simulaid = ... ; ! 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
ERROR procedure error(t); text t; begin ... display text "t" and stop program... end error;
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).
LOWERBOUND integer procedure lowerbound(a,i); <type> array a; integer i; UPPERBOUND integer procedure upperbound(a,i); <type> array a; integer i;
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.
DRAW Boolean procedure draw (a,U); name U; long real a; integer U; The value is true with the probability a, false with the probability 1 - a. It is always true if a >= 1 and always false if a <= 0. RANDINT integer procedure randint (a,b,U); name U; integer a,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. UNIFORM long real procedure uniform (a,b,U); name U; long real a,b; integer U; The value is uniformly distributed in the interval a <= u < b. If b < a, the call constitutes an error. NORMAL long real procedure normal (a,b,U); name U; long real a,b; integer U; The value is normally distributed with mean a and standard deviation b. An approximation formula may be used for the normal distribution function. NEGEXP long real procedure negexp (a,U); name U; long real a; integer U; 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. POISSON integer procedure Poisson (a,U); name U; long real a; integer U; 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. ERLANG long real procedure Erlang (a,b,U); name U; long real a,b; integer U; 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. DISCRETE integer procedure discrete (A,U); name U; <real-type> array A; integer U; 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. LINEAR long real procedure linear (A,B,U); name U; <real-type> array A,B; integer U; 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 HISTD integer procedure histd (A,U); name U; <real-type> array A; integer U; 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: text procedure datetime; 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: long real procedure cputime; The value is the number of processor seconds spent by the calling program. CLOCKTIME: long real procedure clocktime; The value is the number of seconds since midnight.
HISTO: procedure histo(A,B,c,d); real array A,B; real c,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.