;==================================================
;  PROGRAM TITLE:       Random Number Generator
;
;  WRITTEN BY:          Raymond E. Penley
;  DATE WRITTEN:        27 June 1980
;
;  WRITTEN FOR:         Pascal/Z Users Group
;
;  SUMMARY:
;       Implements a Fibonacci series Random number generator.
;       RANDOM will return numbers from 0 to x
;
;               Call as                   Returns
;               -------                 ------------
;           real := RANDOM(10);         0.0 to 10.0
;           real := RANDOM(112);        0.0 to 112.0
;            I := TRUNC(RANDOM(10));      0 to 10
;
; **
;   Add these lines to your PASCAL source program:
;
;     Procedure SEEDRAND; EXTERNAL;
;     Functin RANDOM(X: Integer): REAL; external;
;
;   Also within the body of the main program
;   but BEFORE calling RANDOM(X);
;
;         SEEDRAND;
;
;*** What would happen if you did not call SEEDRAND ? ***
;
;===============================================
;
; PROCEDURE SEEDRAND;
; (* INITIAL VALUES FOR SEED1 AND SEED2 ARE HERE  *)
;
       NAME RANDOM
       ENTRY SEEDRAND,RANDOM
;
SEEDRAND:
       ENTR    D,2,0
;    SEED1 := 10946;
       MVI     0(IY),42
       MVI     -1(IY),194
;    SEED2 := 17711
; END;
       MVI     -2(IY),69
       MVI     -3(IY),47
       EXIT    D,0
;
;
;
; Function Random(x: integer): real;
; (*
; GLOBAL
;   SEED1, SEED2 : INTEGER              *)
; CONST
;   factor = Maxint;
;   HALFINT = 16383; (* 1/2 OF MAXINT *)
; VAR
;   x1 : real;
;   temp1, temp2, HALF_ADDER : INTEGER;

RANDOM:
       ENTR    D,2,10
; (* Take 1/2 of the seeds for the comparison test *)
;   temp1 := SEED1 DIV 2;
       MOV     L,-1(IY)
       MOV     H,0(IY)
       LXI     D,2
       DIVD    D,0
       MOV     -6(IX),H
       MOV     -7(IX),L
;   temp2 := SEED2 DIV 2;
       MOV     L,-3(IY)
       MOV     H,-2(IY)
       LXI     D,2
       DIVD    D,0
       MOV     -8(IX),H
       MOV     -9(IX),L
;   IF (temp1+temp2) >= HALFINT then{the number is too big -}
       MOV     L,-7(IX)
       MOV     H,-6(IX)
       MOV     E,-9(IX)
       MOV     D,-8(IX)
       DADD    D,0
       LXI     D,16383
       GE      D,0
;     { scale it down }
;     HALF_ADDER := temp1 + temp2 - HALFINT
       JNC     L177
       MOV     L,-7(IX)
       MOV     H,-6(IX)
       MOV     E,-9(IX)
       MOV     D,-8(IX)
       DADD    D,0
;   ELSE
       LXI     D,-16383
       DADD    D,0
       MOV     -4(IX),H
       MOV     -5(IX),L
;     HALF_ADDER := temp1 + temp2;
       JMP     L197
L177
       MOV     L,-7(IX)
       MOV     H,-6(IX)
       MOV     E,-9(IX)
       MOV     D,-8(IX)
       DADD    D,0
       MOV     -4(IX),H
       MOV     -5(IX),L
L197
;   SEED1 := SEED2;
       MOV     L,-3(IY)
       MOV     H,-2(IY)
       MOV     0(IY),H
       MOV     -1(IY),L
;   (* Restore from previous DIVision *)
;   SEED2 := HALF_ADDER * 2;
       MOV     L,-5(IX)
       MOV     H,-4(IX)
       DADD    C
       MOV     -2(IY),H
       MOV     -3(IY),L
;   (*---Convert X to real and divide by factor---*)
;   x1 := ((X*1.0)/factor);
       MOV     L,8(IX)
       MOV     H,9(IX)
       PUSH    H
       LXI     H,320
       MOV     D,A
       MOV     E,A
       PUSH    H
       PUSH    D
       CVTF    C
       MULT    D,-4
       CVTF    A,32767
       FDVD    D,-4
       LXI     H,3
       DADD    S
       XCHG
       PUSH    IX
       POP     H
       XCHG
       LXI     B,4
       LDDR
       POP     H
       POP     H
;   (*---Return random number scaled by factor---*)
;   RANDOM := ( SEED2 * x1 );
       MOV     L,-3(IY)
       MOV     H,-2(IY)
       PUSH    H
       LXI     H,-4
       DADD    S
       SPHL
       XCHG
       PUSH    IX
       POP     H
       DCX     H
       DCX     H
       DCX     H
       LXI     B,4
       LDIR
       CVTF    C
       MULT    D,-4
       LXI     H,3
       DADD    S
       XCHG
       PUSH    IX
       POP     H
       LXI     B,13
       DADD    B
       XCHG
       LXI     B,4
       LDDR
       POP     H
       POP     H
; End{ of RANDOM(X) };
       EXIT    D,2