(* ------------------- STAND : 23.10.85 --------------------*) PACKET integer DEFINES text, int, MOD, sign, SIGN, abs, ABS, **, min, max, minint, maxint, random, initialize random , last conversion ok, set conversion : INT PROC minint : -32767 - 1 ENDPROC minint ; INT PROC maxint : 32767 ENDPROC maxint ; TEXT PROC text (INT CONST number) : IF number = minint THEN "-32768" ELIF number < 0 THEN "-" + text(-number) ELIF number <= 9 THEN code (number + 48) ELSE text (number DIV 10) + digit FI . digit : code ( number MOD 10 + 48 ) . ENDPROC text ; TEXT PROC text (INT CONST number, length) : TEXT VAR result := text (number) ; INT CONST number length := LENGTH result ; IF number length < length THEN (length - number length) * " " + result ELIF number length > length THEN length * "*" ELSE result FI ENDPROC text ; INT PROC int (TEXT CONST number) : skip blanks and sign ; get value ; result . skip blanks and sign : BOOL VAR number is positive ; INT VAR pos := 1 ; skip blanks ; IF (number SUB pos) = "-" THEN number is positive := FALSE ; pos INCR 1 ELIF (number SUB pos) = "+" THEN number is positive := TRUE ; pos INCR 1 ELSE number is positive := TRUE FI . get value : INT VAR value ; get first digit ; WHILE is digit REP value := value * 10 + digit ; pos INCR 1 PER ; set conversion ok result . get first digit : IF is digit THEN value := digit ; pos INCR 1 ELSE set conversion (FALSE) ; LEAVE int WITH 0 FI . is digit : 0 <= digit AND digit <= 9 . digit : code (number SUB pos) - 48 . result : IF number is positive THEN value ELSE - value FI . set conversion ok result : skip blanks ; conversion ok := (pos > LENGTH number) . skip blanks : WHILE (number SUB pos) = " " REP pos INCR 1 PER . ENDPROC int ; INT OP MOD (INT CONST left, right) : EXTERNAL 43 ENDOP MOD ; INT PROC sign (INT CONST argument) : IF argument < 0 THEN -1 ELIF argument > 0 THEN 1 ELSE 0 FI ENDPROC sign ; INT OP SIGN (INT CONST argument) : sign (argument) ENDOP SIGN ; INT PROC abs (INT CONST argument) : IF argument > 0 THEN argument ELSE - argument FI ENDPROC abs ; INT OP ABS (INT CONST argument) : abs (argument) ENDOP ABS ; INT OP ** (INT CONST arg, exp) : INT VAR x := arg , z := 1 , counter := exp ; IF exp = 0 THEN LEAVE ** WITH 1 ELIF exp < 0 THEN LEAVE ** WITH 1 DIV arg FI ; WHILE counter >= 2 REP calculate new x and z ; counter := counter DIV 2 ; ENDREP ; z * x . calculate new x and z : IF counter is not even THEN z := z * x FI ; x := x * x . counter is not even : counter MOD 2 = 1 . ENDOP ** ; INT PROC min (INT CONST first, second) : IF first < second THEN first ELSE second FI ENDPROC min ; INT PROC max (INT CONST first, second) : IF first > second THEN first ELSE second FI ENDPROC max ; BOOL VAR conversion ok := TRUE ; BOOL PROC last conversion ok : conversion ok ENDPROC last conversion ok ; PROC set conversion (BOOL CONST success) : conversion ok := success ENDPROC set conversion ; (*******************************************************************) (* *) (* Autor: A. Flammenkamp *) (* RANDOM GENERATOR *) (* *) (* x := 4095 * x MOD (4095*4096+4093) *) (* n+1 n *) (* *) (* Periode: 2**24-4 > 16.0e6 *) (* *) (* Beachte: x = 4096 * x1 + x0, 0 <= x0,x1 < 4096 *) (* *) (*******************************************************************) INT VAR high := 1, low := 0 ; PROC initialize random (INT CONST start) : low := start MOD 4096 ; IF start < 0 THEN high := 256 + 16 + start DIV 4096 ; IF low <> 0 THEN high DECR 1 FI ELSE high := 256 + start DIV 4096 FI ENDPROC initialize random ; INT PROC random (INT CONST lower bound, upper bound) : compute new random value ; normalize high ; normalize low ; map into interval . compute new random value : (* (high,low) := (low-high , 3*high-low) *) high := low - high ; low INCR low - 3 * high . normalize high : IF high < 0 THEN high INCR 4096 ; low DECR 3 FI . normalize low : (* high INCR low DIV 4096 ; low := low MOD 4096 *) IF low >= 4096 THEN low overflow ELIF low < 0 THEN low underflow FI . low overflow : IF low >= 8192 THEN low DECR 8192 ; high INCR 2 ELSE low DECR 4096 ; high INCR 1 ; post normalization FI . post normalization : (* IF (high,low) >= (4095,4093) THEN (high,low) DECR (4095,4093) FI *) IF high >= 4095 THEN IF low >= 4093 THEN high DECR 4095 ; low DECR 4093 ELIF high = 4096 THEN high := 0 ; low INCR 3 FI FI . low underflow : low INCR 4096 ; high DECR 1 . map into interval : INT VAR number := high MOD 16 - 8 ; number INCR 4095 * number + low ; IF lower bound <= upper bound THEN lower bound + number MOD (upper bound - lower bound + 1) ELSE upper bound + number MOD (lower bound - upper bound + 1) FI . ENDPROC random ; ENDPACKET integer ;