Trailing-Edge
-
PDP-10 Archives
-
ALGOL-20_29Jan82
-
algol-sources/alglib.mac
There are 11 other files named alglib.mac in the archive. Click here to see a list.
;
;
;COPYRIGHT (C) 1975,1981,1982 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
;
;
; SUBTTL GLOBAL DECLARATIONS
SEARCH ALGPRM,ALGSYS ; SEARCH PARAMETER FILES
SALL
%TITLE(ALGLIB,ALGOL LIBRARY)
IF2, <PRINTX KL20 Version.>
EXTERNAL %ENTRY,%ALGDR
ENTRY %ALGDA
%ALGDA:
LIT
PRGEND
SUBTTL SHARABLE ALGOTS ENTRY
ENTRY %SHARE
INTERN %ENTRY,%ALGDR,%START,%REN
EXTERN %BEGIN,%OWN,%HEAP,%ALGDA,%JBVER,%JBEDT,%FLAGS,%TRACE
SEARCH ALGPRM,ALGSYS ; SEARCH PARAMETER FILES
SALL
%TITLE(ALGOBJ,ALGOL LIBRARY)
INTERNAL .JBREN,.JBOPS,.JBHDA
%ENTRY=0
%SHARE=0
%ALGDR=400000+.JBHDA
.GTRDI==136 ; [275] GETTAB CODE FOR PROG. RUN DIRECTORY
.GTRFN==137 ; [275] PROGRAM RUN FILENAME
.GTRDV==135 ; [275] PROGRAM RUN DEVICE
.GTRS0==145 ; [275] GETTAB FUNCTION CODE FOR SFD'S
.PTSFD==3 ; [275] PATH. BLOCK INDEX FOR SFD'S
.PTPPN==2 ; [275] INDEX FOR PPN
LOC .JBREN
%REN ; [275] INITIAL REENTER
RELOC
%START: TDZA AX,AX ; START ENTRY POINT
%REN: HRLZI AX,REEN ; REENTER ENTRY POINT
MOVEM AX,.JBOPS ; SAVE START/REENTER FLAG DURING GETSEG
MOVEM A0,IFDAT+1 ; [275] SAVE PROGRAM NAME (PRE 7.00 ONLY)
MOVEM A7,IFDAT ; [275] SAVE RUN PPN FOR FUNCT.
MOVEM A11,IFDAT+2 ; [275] SAVE DEVICE NAME
HRROI A1,.GTRFN ; [275] SETUP TO GET PROGRAM NAME
GETTAB A1, ; [275] GET IT
SKIPA ; [275] FAILED, ASSUME WE ALREADY SAVED IT
MOVEM A1,IFDAT+1 ; [275] SAVE IT
HRROI A1,.GTRDV ; [275] SETUP TO GET DEVICE
GETTAB A1, ; [275] GET IT
SKIPA ; [275] FAILED, ASSUME WE ALREADY SAVED IT
MOVEM A1,IFDAT+2 ; [275] SAVE IT
SETZM PATH+.PTSFD ; [275] INIT. TO HAVE NO SFD'S
MOVSI A1,-5 ; [275] LOAD PTR. TO BUILD PATH BLOCK (5 SFDS)
GET275: HRROI A2,.GTRS0(A1) ; [275] LOAD SFD NAME
GETTAB A2, ; [275] GET IT
JRST GETDON ; [275] FAILED, ASSUME DONE
MOVEM A2,PATH+.PTSFD(A1) ; [275] WORKED, SAVE PTR.
AOBJN A1,GET275 ; [275] LOOP UNTIL DONE
GETDON: SETZM PATH+.PTSFD(A1) ; [275] PUT ZERO AT END OF LIST
HRROI A1,.GTRDI ; [275] SETUP TO GET PPN PROGRAM CAME FROM
GETTAB A1, ; [275] GET IT
MOVE A1,IFDAT ; [275] FAILED, ASSUME WE HAVE IT ALREADY
MOVEM A1,PATH+.PTPPN ; [275] SAVE RUN PPN
SKIPE PATH+.PTSFD ; [275] IF ANY SFD'S AROUND,
MOVEI A1,PATH ; [275] LOAD PATH BLOCK PTR.
MOVEM A1,IFDAT ; [275] ELSE USE PPN
HRLZI A1,%JBEDT
LSH A1,^D9
MOVEI A2,3
HRLZI A5,(SIXBIT/ALG/)
MOVE A3,[POINT 6,A5,17]
MOVE A4,[POINT 7,SEGMES+6,6]
GET2: SETZ A0,
LSHC A0,3
ADDI A0,20 ; TO SIXBIT
IDPB A0,A3
ADDI A0,40 ; TO ASCII
IDPB A0,A4 ; TO ERROR-MESSAGE
SOJG A2,GET2
MOVEM A5,HSEG+1
MOVEM A5,HSEG1+1
GETSYS: MOVEI A0,HSEG
GETSEG A0, ; TRY TO GET SHARABLE ALGOTS
JRST NOSYS ; NOT FOUND
GET1: MOVE AX,.JBOPS ; RESTORE START/REENTER FLAG
HRRI AX,OBJDAT
JRST INITIA ; ENTER TO INITIALIZE
NOSYS: MOVEI A0,HSEG1
GETSEG A0, ; TRY ON DSK INSTEAD
JRST NOSEG ; NOT THERE EITHER
JRST GET1 ; FOUND ON DSK
NOSEG: OUTSTR SEGMES ; [265] COMPLAIN ON TTY
LDB A1,[POINT 3,A0,32] ; [265] ASSUME 2 DIGIT ERROR CODE
ADDI A1,"0" ; [265] CONVERT FIRST DIGIT TO ASCII
CAIE A1,"0" ; [275] SUPPRESS FIRST ZERO
OUTCHR A1 ; [265] TYPE IT
LDB A1,[POINT 3,A0,35] ; [265] GET SECOND DIGIT
ADDI A1,"0" ; [265] CONVERT TO ASCII
OUTCHR A1 ; [265] TYPE IT
OUTSTR CRLF ; [265]
EXIT 1, ; AND RETIRE
JRST GETSYS ; TRY AGAIN IF CONTINUE
HSEG: SIXBIT /SYS/
0 0
0
0
0
HSEG1: SIXBIT /DSK/
0 0
0
0
0
OBJDAT: %BEGIN
%ALGDA
%OWN
%FLAGS,,%HEAP
%JBVER,,%JBEDT
IFDAT: BLOCK 3 ; INITIAL-FILE DATA FOR FUNCT.
%TRACE ; TRACE BUFFER-LENGTH
PATH: BLOCK 12 ; [275] PATH BLOCK FOR FUNCT.
SEGMES: ASCIZ /
?ALGOL object time system ALGNNN.EXE not found, GETSEG error code / ; [265]
CRLF: ASCIZ/
/ ; [265]
ENTRY FUNCT.
FUNCT.: JRST FUNCT ; OVERLAY-HANDLER SUB-ROUTINE ENTRY
LIT
PRGEND %START ; ENTRY POINT
SUBTTL NON-SHARABLE ALGOTS ENTRY
ENTRY %ENTRY
INTERNAL %START,%REN
EXTERNAL %BEGIN,%ALGDR,%OWN,%HEAP,%ALGDA,%JBVER,%JBEDT,%FLAGS,%TRACE
SEARCH ALGPRM,ALGSYS ; SEARCH PARAMETER FILES
SALL
%TITLE(ALGOBJ,ALGOL LIBRARY)
INTERNAL .JBREN
%ENTRY=0
LOC .JBREN
XWD 0,%REN ; INITIAL RENTER
RELOC
%START: TDZA AX,AX ; START ENTRY POINT
%REN: HRLZI AX,REEN ; REENTER ENTRY POINT
HRRI AX,[%BEGIN
%ALGDA
%OWN
%FLAGS,,%HEAP
%JBVER,,%JBEDT
0
0
0
%TRACE]
JRST INITIA ; ENTER TO INITIALIZE
ENTRY FUNCT. ; DUMMY OVERLAY-HANDLER ENTRY-POINT
FUNCT.: OUTSTR [ASCIZ/?ALGNSO Sharable programs may not be overlaid.
/]
EXIT ; FATAL. ONE DAY GO TO DEBUGGER.
LIT
PRGEND %START ; ENTRY POINT
TITLE POWER1/POWER2 - INTEGER/REAL TO INTEGER EXPONENTIATION ROUTINE
;
; POWER1:
;
; AC USE AT ENTRY USE AT EXIT
; -- -------------------- ----------------------
;
; A0 ANSWER
;
; A1 0 = RESULT MUST BE INTEGER
; 1 = RESULT MUST BE REAL
; (COMPILER SAYS SO)
;
; AX RETURN ADDRESS RETURN ADDRESS
;
; (SP) EXPONENT
;
; -1(SP) BASE
;
;
; POWER2:
;
; AC USE AT ENTRY USE AT EXIT
; -- -------------------- ----------------------
;
; A0 ANSWER
;
; AX RETURN ADDRESS RETURN ADDRESS
;
; (SP) EXPONENT
;
; -1(SP) BASE
;
SEARCH ALGPRM,ALGSYS
%ENTER<1,2>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
MLON
LABEL(2): MOVEI A1,2
LABEL(1): POP SP,A2 ; RECOVER EXPONENT
POP SP,A0 ; RECOVER BASE
JUMPN A2,POW101 ; JUMP AHEAD IF EXPONENT IS NON-ZERO
EDIT(050) ; 0^0 IS UNDEFINED, SO GENERATE ERROR MESSAGE
JUMPE A0,POW110 ; [E050] ERROR IF BASE = 0 TOO
XCT [ ; ELSE LOAD THE APPROPRIATE ANSWER FOR X^0
MOVEI A0,1 ; INTEGER ANSWER
MOVSI A0,(1.0) ; REAL ANSWER
MOVSI A0,(1.0) ; REAL ANSWER
](A1) ; (A1 = 0 FOR INTEGER, 1 OR 2 FOR REAL)
JRST (AX) ; RETURN TO CALLING ROUTINE
POW101: JUMPN A1,POW103 ; JUMP AHEAD IF POWER1 ROUTINE IS NEEDED
;
; POWER1 ROUTINE
;
; AC USE AT ENTRY USE WITHIN ROUTINE
; -- ------------------- ---------------------------
;
; A0 CONTAINS BASE ANSWER IS BUILT HERE
;
; A1 UNDEFINED MODIFIED BASE
;
; A2 EXPONENT MODIFIED EXPONENT
;
; AX RETURN ADDRESS RETURN ADDRESS
;
JUMPE A0,(AX) ; ELSE TAKE QUICK EXIT IF BASE = 0
MOVE A1,A0 ; BASE ISN'T 0 - PUT IT IN A1
MOVEI A0,1 ; PREPARE FOR INTEGER MULTIPLICATION
POW102: TRZN A2,1 ; [230] IS LSB SET IN EXPONENT?
JRST .+3 ; [230] NO, SKIP THE MATH
IMUL A0,A1 ; YES, MULTIPLY ANSWER BY MODIFIED BASE
JOV POW109 ; CHECK FOR OVERFLOW
JUMPE A2,(AX) ; RETURN IF FINISHED
IMUL A1,A1 ; ELSE SQUARE BASE
JOV POW109 ; CHECK FOR OVERFLOW
LSH A2,-1 ; SHIFT EXPONENT RIGHT
JRST POW102 ; KEEP DOING IT UNTIL DONE
;
; POWER2 ROUTINE
;
; AC USE AT ENTRY USE WITHIN ROUTINE
; --- ---------------------------------------------------
;
; A0 CONTAINS BASE ANSWER IS BUILT HERE
;
; A1 BASE FLAG: 0=INTEGER MODIFIED BASE
; 1=REAL, 2=OTHER
;
; A2 EXPONENT MODIFIED EXPONENT
;
; A3 UNDEFINED EXPONENT FLAG: 1=POSITIVE, 0=NEGATIVE
;
; AX RETURN ADDRESS RETURN ADDRESS
;
POW103: JUMPE A0,POW107 ; SKIP WHOLE ROUTINE IF BASE = 0
SOJN A1,POW104 ; ELSE IS BASE IN REAL MODE?
FLTR A0,A0 ; NO, CONVERT IT TO REAL
POW104: MOVE A1,A0 ; YES, TRANSFER BASE TO A1
JUMPG A2,POW105 ; JUMP AHEAD IF EXPONENT IS POSITIVE
MOVN A2,A2 ; ELSE MAKE IT POSITIVE
JOV POW109 ; ERROR IF OVERFLOW HAPPENED
TDZA A3,A3 ; ELSE CLEAR POSITIVE FLAG AND SKIP
POW105: MOVEI A3,1 ; SET POSITIVE FLAG
MOVSI A0,(1.0) ; PREPARE FOR MULTIPLICATION/DIVISION
POW106: TRZN A2,1 ; IS LSB SET IN EXPONENT?
JRST .+3 ; NO, SKIP THE MATH
XCT [ ; YES, DO THE APPROPRIATE MATH FUNCTION
FDVR A0,A1 ; DIVIDE IF EXPONENT IS NEGATIVE
FMPR A0,A1 ; MULTIPLY IF EXPONENT IS POSITIVE
](A3) ; (A3 = 0 FOR NEG., 1 FOR POS. EXPONENT)
JFOV POW108 ; CHECK FOR OVERFLOW
JUMPE A2,(AX) ; RETURN TO CALLING ROUTINE IF ALL DONE
FMPR A1,A1 ; ELSE SQUARE BASE
JFOV POW108 ; CHECK FOR OVERFLOW
LSH A2,-1 ; SHIFT EXPONENT RIGHT
JRST POW106 ; KEEP LOOPING UNTIL DONE
POW107: JUMPG A2,(AX) ; BASE IS ZERO - RETURN IF EXPONENT > 0
SYSER2 2,(AX) ; [230] ELSE ERROR - CAN'T HAVE EXPONENT <= 0
POW108: SKIPE A3 ; [230] OVERFLOW - WAS EXPONENT NEGATIVE?
SYSER2 2,(AX) ; NO, A REAL FLOATING OVERFLOW HAPPENED
MOVSI A0,(0.0) ; [230] YES, IT'S OK - SET RESULT TO 0
JRST (AX) ; [230] RETURN TO CALLING ROUTINE
POW109: SYSER2 3,(AX) ; FIXED POINT OVERFLOW
POW110: LIBERR 1,(AX) ; [E050] BASE & EXPONENT BOTH ZERO
LIT
PRGEND
TITLE POWER3 - LONG REAL TO INTEGER EXPONENTIATION ROUTINE
; ON ENTRY:
; THE BASE AND EXPONENT ARE ON THE STACK
; THE LINK IS IN AX
; ON EXIT, THE RESULT (TYPE LONG REAL) IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<3>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(3): POP SP,A7 ; RECOVER EXPONENT
POP SP,A4
EXCH AX,(SP) ; RECOVER BASE
MOVE A3,AX ; AND SAVE LINK
JUMPN A7,POW302 ; EXPONENT = 0?
EDIT(050); 0^0 is undefined, so generate error message
JUMPE A3,POW308 ; [E050] ERROR IF BASE = 0.0&&0
MOVSI A0,(1.0)
MOVEI A1,0 ; YES - L^0 IS ALWAYS 1.0&&0
POW301: POPJ SP,0
POW302: JUMPE A3,POW305 ; BASE = 0?
JUMPGE A7,POW303 ; NO - EXPONENT POSITIVE?
MOVN A7,A7 ; NO - NEGATE IT
JOV POW307 ; CHECK OVERFLOW
TDZA A10,A10 ; AND CLEAR POSITIVE FLAG
POW303: MOVEI A10,1 ; SET POSITIVE FLAG
MOVSI A0,(1.0)
MOVEI A1,0 ; PREPARE FOR MULTIPLICATION/DIVISION
POW304: TRZN A7,000001 ; BIT SET IN EXPONENT?
JRST .+3 ; NO
XCT [
DFDV A0,A3
DFMP A0,A3](A10)
JFOV POW306 ; YES - MULTIPLY/DIVIDE
JUMPE A7,POW301 ; EXIT IF FINISHED
DFMP A3,A3 ; OTHERWISE SQUARE MULTIPLIER
EDIT (236) ; [236] FIX FLOATING OVERFLOW FOR NEG. EXPONENTS
JFOV POW306 ; [236] JUMP AHEAD IF ERROR HAPPENED
LSH A7,-1 ; SHIFT AROUND EXPONENT
JRST POW304 ; AND CARRY ON
POW305: SETZB A0,A1 ; BASE = 0
JUMPG A7,POW301 ; EXIT IF EXPONENT > 0
POW306: TRNE A10,1 ; [236] OVERFLOW - WAS EXPONENT NEGATIVE?
SYSER2 2,@(SP) ; [236] NO, A REAL FLOATING OVERFLOW HAPPENED
SETZB A0,A1 ; [236] YES, SET ANSWER TO 0.0
JRST POW301 ; [236] GO RETURN TO CALLING ROUTINE
POW307: SYSER2 3,@(SP) ; FIXED POINT OVERFLOW
POW308: LIBERR 1,@(SP) ; [E050] BASE & EXPONENT BOTH ZERO
LIT
PRGEND
TITLE POWER4 - INTEGER/REAL TO REAL EXPONENTIATION ROUTINE
; ON ENTRY:
; THE BASE AND EXPONENT ARE ON THE STACK
; A1 = 0 IF BASE IS INTEGER
; A1 = 1 IF BASE IS REAL
; THE LINK IS IN AX
; ON EXIT, THE RESULT (TYPE REAL) IS IN A0
SEARCH ALGPRM,ALGSYS
%ENTER<4>
EXTLAB<7,104,105>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(4): POP SP,A2 ; RECOVER EXPONENT
EXCH AX,(SP) ; RECOVER BASE
MOVE A0,AX ; AND SAVE LINK
JUMPN A2,POW401 ; EXPONENT = 0?
EDIT(050); 0^0 is undefined, so generate error message
JUMPN A0,POW405 ; [E050] O.K. IF BASE NON-ZERO
POW403: LIBERR 1,@(SP) ; NO - COMPLAIN
POW401: JUMPN A1,.+2
JSP AX,LABEL(7) ; CONVERT BASE TO REAL IF NECESSARY
JUMPLE A0,POW402 ; BASE <= 0?
PUSH SP,A2 ; NO - SAVE EXPONENT
PUSHJ SP,LABEL(105) ; AND TAKE LOGARITHM OF BASE
POP SP,A1 ; RESTORE EXPONENT
JUMPE A0,POW405 ; QUICK EXIT IF RESULT ZERO
FMPR A0,A1 ; OTHERWISE MULTIPLY BY EXPONENT
JRST LABEL(104) ; AND TAKE EXPONENTIAL
POW402: JUMPN A0,POW403 ; BASE = 0?
POW404: JUMPL A2,POW403 ; YES - EXPONENT < 0?
TDZA A0,A0 ; NO - RESULT IS 0.0
POW405: MOVSI A0,(1.0) ; RESULT IS 1.0
POPJ SP,0
LIT
PRGEND
TITLE POWER5 - INTEGER/REAL TO LONG REAL, LONG REAL TO REAL/LONG REAL EXPONENTIATION ROUTINE
; ON ENTRY:
; THE BASE AND EXPONENT ARE ON THE STACK
; A1 = 0 IF INTEGER TO LONG REAL
; A1 = 1 IF REAL TO LONG REAL
; A1 = 2 IF LONG REAL TO REAL
; A1 = 3 IF LONG REAL TO LONG REAL
; THE LINK IS IN AX
; ON EXIT, THE RESULT (TYPE LONG REAL) IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<5>
EXTLAB<10,13,21,120,121>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(5): JRST @POW501(A1) ; USE APPROPRIATE SEQUENCE
POW501: XWD 0,POW502 ; I^LR
XWD 0,POW503 ; R^LR
XWD 0,POW504 ; LR^R
XWD 0,POW505 ; LR^LR
POW502: POP SP,A4
POP SP,A3 ; RECOVER EXPONENT
EXCH AX,(SP) ; RECOVER BASE
MOVE A0,AX ; AND SAVE LINK
JSP AX,LABEL(10) ; CONVERT BASE TO LONG REAL
JRST POW506
POW503: POP SP,A4
POP SP,A3 ; RECOVER EXPONENT
EXCH AX,(SP) ; RECOVER BASE
MOVE A0,AX ; AND SAVE LINK
JSP AX,LABEL(13) ; CONVERT BASE TO LONG REAL
JRST POW506
POW504: POP SP,A0 ; RECOVER EXPONENT
POP SP,A4
EXCH AX,(SP) ; RECOVER BASE
MOVE A3,AX ; AND SAVE LINK
JSP AX,LABEL(13) ; CONVERT EXPONENT TO LONG REAL
EXCH A0,A3
EXCH A1,A4 ; GET THINGS IN RIGHT ACCUMULATORS
JRST POW506
POW505: POP SP,A4
POP SP,A3 ; RECOVER EXPONENT
POP SP,A1
EXCH AX,(SP) ; RECOVER BASE
MOVE A0,AX ; AND SAVE LINK
POW506: JUMPN A3,POW507 ; EXPONENT = 0?
EDIT(050); 0^0 is undefined, so generate error message
JUMPE A0,POW509 ; [E050] ERROR IF BASE ALSO ZERO
MOVSI A0,(1.0)
MOVEI A1,0
POPJ SP,0 ; YES - RESULT IS 1.0&&0
POW507: JUMPLE A0,POW508 ; BASE <= 0?
PUSH SP,A3
PUSH SP,A4 ; NO - SAVE EXPONENT
PUSHJ SP,LABEL(121) ; AND TAKE LOGARITHM OF BASE
POP SP,A4
POP SP,A3 ; RESTORE EXPONENT
JUMPE A0,LABEL(120) ; QUICK EXIT IF RESULT ZERO
MOVEI AX,A3
PUSHJ SP,LABEL(21) ; OTHERWISE MULTIPLY BY EXPONENT
JRST LABEL(120) ; AND TAKE EXPONENTIAL
POW508: JUMPE A0,POW510 ; BASE = 0?
POW509: LIBERR 1,@(SP) ; NO - COMPLAIN
POW510: JUMPL A3,POW509 ; YES - EXPONENT < 0?
SETZB A0,A1 ; NO - RESULT IS 0.0&&0
POW511: POPJ SP,0
LIT
PRGEND
TITLE DSIGN - DUMMY BODY FOR SIGN
; INTEGER PROCEDURE SIGN(I); VALUE I; INTEGER I;
; INTEGER PROCEDURE SIGN(X); VALUE X; REAL X;
; INTEGER PROCEDURE SIGN(D); VALUE D; LONG REAL D;
.EXIT=1
.IXD=3
SEARCH ALGPRM,ALGSYS
%ENTER<223>
EXTERNAL %ALGDR
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<6>
LABEL(223): JSP AX,PARAM
Z ; ZERO POINTER. ROUTINE ITSELF CALLS TRACE
XWD 0,4
XWD $PRO!$I!$SIM,2
XWD $VAR!$WA!$FOV,.IXD
MOVE A0,.IXD(DL) ; GET ARGUMENT
JSP AX,LABEL(6) ; AND ITS SIGN
MOVEM A0,.EXIT+1(DL)
JRST .EXIT(DL)
LIT
PRGEND
TITLE SIGN - SIGN ROUTINE
; ON ENTRY:
; THE ARGUMENT (INTEGER, REAL OR THE HIGH ORDER WORD OF LONG REAL) IS IN A0
; THE LINK IS IN AX
; ON EXIT:
; THE RESULT: -1 IF ARGUMENT < 0
; 0 IF ARGUMENT = 0
; 1 IF ARGUMENT > 0
; IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(6,SIGN)
JUMPE A0,(AX) ; EXIT IF ZERO ARGUMENT
JUMPL A0,SIGN1 ; ARGUMENT < 0?
MOVEI A0,1 ; NO - RESULT IS 1
JRST (AX)
SIGN1: MOVNI A0,1 ; YES - RESULT IS -1
JRST (AX)
LIT
PRGEND
TITLE DABS - DUMMY BODY FOR ABS
; INTEGER PROCEDURE ABS(I); VALUE I; INTEGER I;
; REAL PROCEDURE ABS(X); VALUE X; REAL X;
; LONG REAL PROCEDURE ABS(D); VALUE D; LONG REAL D;
.EXIT=1
.IX=3
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<222>
EXTERNAL %ALGDR
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
ABS:
LABEL(222): MOVE A1,(SP) ; GET PROGRAM LINK
HRRZ A0,(A1) ; NUMBER OF PARAMETERS+1
CAIE A0,2 ; TWO?
SYSER1 10,0 ; NO - COMPLAIN
HLRZ A0,1(A1)
ANDI A0,$TYPE ; GET TYPE
CAIN A0,$I
JRST DABS2 ; INTEGER I
CAIN A0,$R
JRST DABS3 ; REAL
CAIE A0,$LR ; LONG REAL?
SYSER1 7,0 ; NO - COMPLAIN
JSP AX,PARAM ; (D)
EXP PMB
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL)
JUMPGE A0,DABS1
DMOVN A0,A0
DABS1: DMOVEM A0,.EXIT+1(DL)
JRST .EXIT(DL)
DABS2: JSP AX,PARAM ; (I)
XWD 0,3
XWD $PRO!$I!$SIM,2
XWD $VAR!$I!$FOV,.IX
JRST DABS4
DABS3: JSP AX,PARAM ; (R)
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.IX
DABS4: MOVM A0,.IX(DL) ; GET MAGNITUDE
MOVEM A0,.EXIT+1(DL)
JRST .EXIT(DL)
PMB:
PMB: 0 ; PROFILE WORD
1,,3
SIXBIT/ABS/
LIT
PRGEND
TITLE DENTIER - DUMMY BODY FOR ENTIER
; INTEGER PROCEDURE ENTIER(X); VALUE X; REAL X;
; INTEGER PROCEDURE ENTIER(D); VALUE D; LONG REAL D;
.EXIT=1
.XD=3
SEARCH ALGPRM,ALGSYS
%ENTER<224>
EXTERNAL %ALGDR
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<11,14>
LABEL(224): JSP AX,PARAM
Z
XWD 0,4
XWD $PRO!$I!$SIM,2
XWD $VAR!$WF!$FOV,.XD
MOVE A1,PRGLNK(DL) ; GET PROGRAM LINK
HLRZ A2,-1(A1)
ANDI A2,$TYPE ; GET TYPE OF PARAMETER
MOVEI AX,DENT1 ; SET RETURN LINK
MOVE A0,.XD(DL) ; AND LOAD FIRST ARGUMENT WORD
CAIN A2,$R ; REAL?
JRST LABEL(11) ; YES - USE ENTIER
MOVE A1,.XD+1(DL) ; NO - LOAD SECOND WORD OF ARGUMENT
JRST LABEL(14) ; AND USE ENTIEL
DENT1: MOVEM A0,.EXIT+1(DL) ; RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE DINT - DUMMY BODY FOR INT
; INTEGER PROCEDURE INT(B); VALUE B; BOOLEAN B;
.EXIT=1
.B=2
SEARCH ALGPRM,ALGSYS
LIBENT(225,INT)
XWD 0,2
XWD $PRO!$I!$SIM,2
XWD $VAR!$B!$FOV,.B
JRST .EXIT(DL) ; RESULT TRANSFERRED AUTOMATICALLY!
LIT
PRGEND
TITLE DBOOL - DUMMY BODY FOR BOOL
; BOOLEAN PROCEDURE BOOL(I); VALUE I; INTEGER I;
.EXIT=1
.I=2
SEARCH ALGPRM,ALGSYS
LIBENT(226,BOOL)
XWD 0,2
XWD $PRO!$B!$SIM,2
XWD $VAR!$I!$FOV,.I
JRST .EXIT(DL) ; RESULT TRANSFERRED AUTOMATICALLY!
LIT
PRGEND
TITLE IR - INTEGER TO REAL CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
%ENTER<7>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(7): FLTR A0,A0
JRST (AX)
LIT
PRGEND
TITLE ILR - INTEGER TO LONG REAL CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<10>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(10):
ASHC A0,-^D35 ; SHIFT INTO A1, PROPAGATE SIGN
TLC A0,276000 ; SET EXPONENT IN A0
DFAD A0,[EXP 0,0] ; NORMALIZE
JRST (AX)
LIT
PRGEND
TITLE ENTIER/RI - ENTIER/REAL TO INTEGER CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
SALL
%ENTER<12>
%SUBTTL(ALGLIB,ALGOL LIBRARY)
STDENT(11,ENTIER)
ENT1: MULI A0,400 ; ENTIER - SEPARATE EXPONENT AND MANTISSA
EXCH A0,A1
TSC A1,A1 ; FIX UP EXPONENT
ASH A0,-243(A1) ; AND SHIFT MANTISSA TO FORM INTEGER
JRST (AX)
LABEL(12):FIXR A0,A0 ; RI - CONVERT TO NEAREST INTEGER
JRST (AX)
LIT
PRGEND
TITLE RLR - REAL TO LONG REAL CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<13>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(13): MOVEI A1,0 ; ZERO LOW ORDER WORD
JRST (AX)
LIT
PRGEND
TITLE ENTIEL/LRI - ENTIEL/LONG REAL TO INTEGER CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0,A1
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
%ENTER<15>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(15): DFAD A0,[
EXP 0.5,0.0] ; LI - ADD 0.5
JRST LRI1
STDENT(14,ENTIER)
LRI1: PUSH SP,A2 ;[250] SAVE A2 BEFORE WE STEP ON IT
HLRZ A2,A0 ; ENTIEL
LSH A2,-11
ANDI A2,000377 ; EXTRACT HIGH ORDER EXPONENT
TLZ A0,377000 ; AND CLEAR IT OUT
JUMPGE A0,.+3 ; NUMBER POSITIVE?
TRC A2,000377 ; NO - COMPLEMENT EXTRACTED EXPONENT
TLO A0,377000 ; AND SET ALL ONES
ASHC A0,-233(A2) ; SHIFT MANTISSA TO INTEGER
POP SP,A2 ;[250] RESTORE A2
JRST (AX)
LIT
PRGEND
TITLE LRR - LONG REAL TO REAL CONVERSION ROUTINE
; ON ENTRY:
; THE ARGUMENT IS IN A0,A1
; THE LINK IS IN AX
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
%ENTER<16>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
MLON
LABEL(16): JUMPGE A0,.+3 ; ARGUMENT POSITIVE?
DMOVN A0,A0 ; NO - NEGATE IT
TLZA A1,400000 ; AND CLEAR BIT 0 FLAG
TLO A1,400000 ; YES - SET BIT 0 FLAG
TLNN A1,200000 ; ROUNDING REQUIRED?
JRST LR1 ; NO
CAMN A0,[
XWD 377777,777777] ; NUMBER TOO LARGE?
SYSER2 2,0 ; YES - REPORT OVERFLOW
ADDI A0,1 ; NO
TLO A0,400 ; CARRY
LR1: JUMPL A1,(AX) ; EXIT IF POSITIVE
MOVN A0,A0 ; OTHEWISE NEGATE
JRST (AX)
LIT
PRGEND
TITLE DSINE - DUMMY BODY FOR SINE
; REAL PROCEDURE SIN(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<200>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<100>
LABEL(200): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(100) ; CALL SINE
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE DCOSINE - DUMMY BODY FOR COSINE
; REAL PROCEDURE COS(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<201>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<101>
LABEL(201): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(101) ; CALL COSINE
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE SINE/COSINE - SINGLE PRECISION SINE/COSINE ROUTINES
; TRANSCRIBED FROM LIB40 V.22/EY/KK
; METHOD: TAYLOR SERIES WITH FIVE TERMS
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(101,COSINE)
MOVE A1,A0 ; COSINE
FADR A1,SIN4 ; ADD PI/2
MOVM A1,A1 ; AND TAKE MAGNITUDE
CAMGE A1,SIN6 ; VERY SMALL?
MOVN A0,A0 ; YES - CALCULATE COS(-X)
FADR A0,SIN4
MOVM A1,A0
JRST COS2
STDENT(100,SINE)
FADRI A0,0.0 ; [272] ENSURE NORMALISED
MOVM A1,A0 ; SINE - GET MAGNITUDE OF X
CAMGE A1,SIN6 ; VERY SMALL?
POPJ SP, ; [272] YES - QUICK EXIT: SIN(X) = X
COS2: FDVR A1,SIN4 ; [272] Y:=ABS(X)/(PI/2)
CAMGE A1,[1.0] ; [272] LESS THAN 1.0?
JRST SIN1 ; YES
MULI A1,400 ; NO - SEPARATE EXPONENT AND MANTISSA
LSH A2,-202(A1)
TLZ A2,(1B0) ; [272] SHIFT OUT INTEGER PART OF NUMBER
MOVEI A1,200 ; PREPARE NEW EXPONENT
ROT A2,3 ; SAVE QUADRANT BITS
LSHC A1,33 ; AND BRING INTO RANGE (0,1)
FADRI A1,0.0 ; [272] NORMALIZE
JUMPE A2,SIN1 ; OK IF IN FIRST QUADRANT
TLCE A2,1000 ; [272] SECOND OR FOURTH QUADRANT
FSBRI A1,(1.0) ; [272] YES - SUBTRACT 1.0
TLCE A2,3000 ; [272] SECOND QUADRANT
TLNN A2,3000 ; [272] OR THIRD QUADRANT?
MOVN A1,A1 ; YES - NEGATE
SIN1: SKIPGE A0 ; [272] X < 0?
MOVN A1,A1 ; YES - NEGATE Y
MOVE A2,A1 ; [272] SAVE Y
FMPR A1,A1 ; AND FORM Y^2
MOVEI A3,3
MOVE A0,SIN5
SIN3: FMPR A0,A1
FAD A0,SIN4(A3) ; [272]
SOJGE A3,SIN3
FMPR A0,A2 ; FORM POLYNOMIAL IN Y
POPJ SP, ; [272]
SIN4: 201622,,077325 ; [272] PI/2
577265,,210372 ; [272] -(PI/2)^3/3!
175506,,321276 ; [272] (PI/2)^5/5!
606315,,546346 ; [272] -(PI/2)^7/7!
SIN5: 164475,,536722 ; [272] (PI/2)^9/9!
SIN6: 162400,,000000 ; [272] 2&-15
LIT
PRGEND
TITLE DARCSIN - DUMMY BODY FOR ARCSINE
; REAL PROCEDURE ARCSIN(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<207>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<107>
LABEL(207): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(107) ; CALL ARCSINE
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE ARCSIN - SINGLE PRECISION INVERSE SINE ROUTINE
; REWRITE OF LIB40 V.27/EY/KK/DMN
; METHOD:
;
; IF X < -1.0 OR X > 1.0 AN ERROR RESULTS
;
; IF -1 <= X <= 1, ARCSIN(X) = ARCTAN(X/SQRT(1 - X^2))
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
EXTLAB<102,103>
STDENT(107,ARCSIN)
MOVM A1,A0 ; MAGNITUDE OF ARGUMENT
CAML A1,[
XWD 201400,000000] ; STRICTLY IN RANGE?
JRST ARCS1 ; NO
MOVE A4,A0 ; TAKE SAFE COPY OF X
MOVN A1,A0
FMPR A0,A1
FADRI A0,201400 ; FORM 1 - X^2
PUSHJ SP,LABEL(103) ; AND TAKE SQRT
FDVRM A4,A0 ; FORM X/SQRT(1 - X^2)
JRST LABEL(102) ; AND LET ARCTAN FINISH OFF
ARCS1: CAME A1,[
XWD 201400,000000] ; X = -1.0 OR 1.0?
LIBERR 3,@(SP) ; NO
FMPR A0,[
XWD 201622,077325] ; YES - RETURN -PI/2 OR PI/2
POPJ SP,0
LIT
PRGEND
TITLE DARCCOS - DUMMY BODY FOR ARCCOS
; REAL PROCEDURE ARCCOS(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<210>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<110>
LABEL(210): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(110) ; CALL ARCCOS
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE ARCCOS - SINGLE PRECISION INVERSE COSINE ROUTINE
; REWRITE OF LIB40 V.27/KK/DMN
; METHOD:
;
; IF X < -1.0 OR X > 1.0 AN ERROR RESULTS
; IF X = -1.0, ARCCOS(X) = PI
; IF -1.0 < X < 0, ARCCOS(X) = PI + ARCTAN(SQRT(1 - X^2)/X)
; IF X = 0, ARCCOS(X) = PI/2
; IF 0 < X < 1.0, ARCCOS(X) = ARCTAN(SQRT(1 - X^2)/X)
; IF X = 1.0, ARCCOS(X) = 0
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
EXTLAB<102,103>
STDENT(110,ARCCOS)
MOVM A1,A0 ; MAGNITUDE OF ARGUMENT
CAML A1,[
XWD 201400,000000] ; STRICTLY IN RANGE?
JRST ARCC1 ; NO
JUMPE A0,ARCC2 ; SPECIAL CASE X = 0?
MOVE A4,A0 ; SAFE COPY OF ARGUMENT
MOVN A1,A0
FMPR A0,A1
FADRI A0,201400 ; FORM 1 - X^2
PUSHJ SP,LABEL(103) ; AND TAKE SQRT
FDVR A0,A4 ; AND DIVIDE BY X
JUMPG A4,LABEL(102) ; LET ARCTAN PROCEDE IF X > 0
PUSHJ SP,LABEL(102) ; OTHERWISE CALL ARCTAN
FADR A0,[
XWD 202622,077325] ; AND ADD PI
POPJ SP,0
ARCC1: CAME A1,[
XWD 201400,000000] ; X = -1.0 OR 1.0
LIBERR 3,@(SP) ; NO - COMPLAIN
JUMPL A0,.+2 ; X = 1.0?
TDZA A0,A0 ; YES - RESULT IS 0
MOVE A0,[
202622,,077325] ; NO - RESULT IS PI.
POPJ SP,0
ARCC2: MOVE A0,[
XWD 201622,077325] ; X = 0, RESULT IS PI/2
POPJ SP,0
LIT
PRGEND
TITLE DARCTAN - DUMMY BODY FOR ARCTAN
; REAL PROCEDURE ARCTAN(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<202>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<102>
LABEL(202): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(102) ; CALL ARCTAN
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE ARCTAN - SINGLE PRECISION INVERSE TANGENT ROUTINE
; TRANSCRIBED FROM LIB40 V.22/EY/KK
; METHOD:
;
; IF X < 0, ARCTAN(X) = -ARCTAN(-X)
;
; IF 0 <= X < 2^(-27), ARCTAN(X) = X
;
; IF 2^(-27) <= X <= 1.0:
;
; ARCTAN(X) = X*(B0 + A1/(X^2 + B1 + A2/(X^2 + B2 + A3/(X^2 + B3))))
;
; IF 1.0 < X < 2^27, ARCTAN(X) = PI/2 - ARCTAN(1/X)
;
; IF X >= 2^27, ARCTAN(X) = PI/2
; ON ENTRY:
; THE ARGUMENT IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(102,ARCTAN)
MOVM A1,A0 ; GET ABS(X)
CAMGE A1,[
XWD 145400,000000] ; ABS(X) < 2^(-27)?
JRST ARCT3 ; YES - ARCTAN(X) = X
CAMGE A1,[
XWD 233400,000000] ; ABS(X) >= 2^27?
JRST ARCT1 ; NO
JUMPL A0,.+2 ; YES: X < 0?
SKIPA A1,ARCT4 ; NO - RESULT IS PI/2
MOVN A1,ARCT4 ; YES - RESULT IS -PI/2
MOVE A0,A1
POPJ SP,0
ARCT1: HRRI A0,0 ; CLEAR RANGE FLAG
MOVSI A2,201400
CAMG A1,A2 ; ABS(X) > 1.0?
JRST ARCT2 ; NO
FDVRM A2,A1 ; YES - FORM 1/ABS(X)
SETCA A0,0 ; SET RANGE FLAG AND INVERT SIGN
ARCT2: MOVE A2,A1
FMPR A2,A2 ; FORM X^2
MOVE A3,ARCT8
FADR A3,A2 ; X^2 + B3
MOVE A4,ARCT11
FDVR A4,A3
FADR A4,ARCT7
FADR A4,A2 ; X^2 + B2 + A3/(X^2 + B3)
MOVE A3,ARCT10
FDVR A3,A4
FADR A3,ARCT6
FADR A3,A2 ; X^2 + B1 + A2/(X^2 + B2 + A3/(X^2 + B3))
MOVE A4,ARCT9
FDVR A4,A3
FADR A4,ARCT5 ; B0 + A1/(X^2 + B1 + A2/(X^2 + B2 + A3/(X^2 + B3)))
FMPR A1,A4 ; MULTIPLY BY ABS(X) TO GIVE ARCTAN(X)
TRNE A0,-1 ; RANGE FLAG SET?
FSBR A1,ARCT4 ; YES - SUBTRACT PI/2
EXCH A0,A1 ; LOAD UP RESULT
JUMPGE A1,ARCT3 ; SHOULD IT BE NEGATIVE?
MOVN A0,A0 ; YES- NEGATE IT
ARCT3: POPJ SP,0
ARCT4: XWD 201622,077325 ; PI/2
ARCT5: XWD 176545,543401 ; B0
ARCT6: XWD 203660,615617 ; B1
ARCT7: XWD 202650,373270 ; B2
ARCT8: XWD 201562,663021 ; B3
ARCT9: XWD 202732,621643 ; A1
ARCT10: XWD 574071,125540 ; A2
ARCT11: XWD 600360,700773 ; A3
LIT
PRGEND
TITLE DSQRT - DUMMY BODY FOR SQRT
; REAL PROCEDURE SQRT(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<203>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<103>
LABEL(203): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(103) ; CALL SQRT
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE SQRT - SINGLE PRECISION SQUARE ROOT ROUTINE
; TRANSCRIBED FROM LIB40 V.27I/TL/TWE
; METHOD: LINEAR APPROXIMATION WITH TWO NEWTON-RAPHESON ITERATIONS
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(103,SQRT)
JUMPGE A0,SQRT1 ; ENSURE POSITIVE ARGUMENT
LIBERR 0,@(SP) ; NO - COMPLAIN
SQRT1: JUMPE A0,SQRT4 ; QUICK EXIT FOR ZERO ARGUMENT
MOVEI A1,0
ROTC A0,11 ; GET EXPONENT IN A1
LSH A0,-11 ; AND CLEAR IT OUT OF ARGUMENT
SUBI A1,201 ; TRUE EXPONENT - 1
ROT A1,-1 ; HALVE AND SAVE ODD/EVEN BIT IN A1
JUMPL A1,SQRT2 ; 0.25 <= FRACTION < 0.5?
TLO A0,177000 ; YES - FIX UP EXPONENT TO FORM Y
MOVE A2,A0
FMPRI A2,200640 ; R1 = LINEAR APPROXIMATION TO SQRT(Y)
FADRI A2,177465 ; = (832*Y + 309)/1024
JRST SQRT3
SQRT2: TLO A0,200000 ; NO - FIX UP EXPONENT TO FORM Y
MOVE A2,A0
FMPRI A2,200450 ; R1 = LINEAR APPROXIMATION TO SQRT(Y)
FADRI A2,177660 ; = (37*Y + 27)/64
SQRT3: MOVE A3,A0
FDVR A3,A2
FADR A3,A2 ; FIRST NEWTON-RAPHESON ITERATION:
FSC A3,-1 ; R2 = (Y/R1 + R1)/2
FDVR A0,A3 ; SECOND NEWTON-RAPHESON ITERATION:
FADR A0,A3 ; R3 = (Y/R2 + R2)/2
FSC A0,(A1) ; SCALE BACK TO SIZE (INCLUDES HALVING TO R3)
SQRT4: POPJ SP,0
LIT
PRGEND
TITLE DLN - DUMMY BODY FOR LN
; REAL PROCEDURE LN(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<205>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<105>
LABEL(205): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(105) ; CALL LN
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LN - SINGLE PRECISION LOGARITHM ROUTINE
; REWRITE OF LIB40 V.22/KK/DMN
; METHOD:
;
; X = F*2^I, WHERE 0.5 <= F < 1
;
; LN(X) = LN(2)*(I + LOG2(F))
;
; LOG2(F) = C1*Z + C3*Z^3 + C5*Z^5 - 0.5
;
; WHERE Z = (F - SQRT(0.5))/(F + SQRT(0.5))
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(105,LN)
JUMPG A0,.+2 ; ARGUMENT POSITIVE?
LIBERR 1,@(SP) ; NO - COMPLAIN
CAMN A0,[
XWD 201400,000000] ; X = 1.0?
JRST LN1 ; YES - QUICK EXIT
ASHC A0,-33 ; SEPARATE EXPONENT AND MANTISSA
HRLI A0,233000
FSBRI A0,210401 ; FORM I - 0.5, FLOATING POINT
ASH A1,-10
TLO A1,200000 ; FIX UP F
MOVE A2,A1
FSBR A1,LN2
FADR A2,LN2
FDVRB A1,A2 ; Z = (F - SQRT(0.5))/(F + SQRT(0.5))
FMPR A1,A1 ; FORM Z^2
MOVE A3,LN5
FMPR A3,A1
FADR A3,LN4
FMPR A3,A1
FADR A3,LN3
FMPR A2,A3 ; C1*Z + C3*Z^3 + C5*Z^5
FADR A0,A2 ; ADD I - 0.5
FMPR A0,[
XWD 200542,710300] ; AND MULTIPLY BY LN(2)
POPJ SP,0
LN1: MOVEI A0,0
POPJ SP,0
LN2: XWD 200552,023632 ; SQRT(0.5)
LN3: XWD 202561,251002 ; C1
LN4: XWD 200754,213604 ; C3
LN5: XWD 200462,432521 ; C5
LIT
PRGEND
TITLE DTAN - DUMMY BODY FOR TAN
; REAL PROCEDURE TAN(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<206>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<106>
LABEL(206): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(106) ; CALL TAN
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE TAN - SINGLE PRECISION TANGENT ROUTINE
; REWRITE OF ATLAS EXTRACODE 1735
; METHOD:
;
; X = (N+Y)*PI/2, WHERE N IS AN INTEGER, AND -0.5 <= Y < 0.5
;
; IF N IS EVEN, TAN(X) = P(Y)/(1 - Y^2)
;
; IF N IS ODD, TAN(X) = -(1 - Y^2)/P(Y)
;
; WHERE P(Y) IS AN ODD POLYNOMIAL IN Y
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE REULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(106,TAN)
JUMPE A0,TAN4 ; QUICK EXIT FOR ZERO
FMPR A0,[
XWD 200505,746034] ; MULTIPLY BY 2/PI
MOVM A2,A0 ; ABS(X)/(PI/2)
MOVEI A1,1 ; SET FLAG FOR EVEN N
CAMGE A2,[
XWD 200400,000000] ; LESS THAN 0.5?
JRST TAN1 ; YES - TAKE SHORT CUT
FSBRI A2,200400 ; NO - SUBTRACT 0.5
MULI A2,400 ; SEPARATE EXPONENT AND MANTISSA
EXCH A2,A3 ; THINGS ARE NOW THE WRONG WAY ROUND
MOVEI A1,0
CAIL A3,233 ; WILL SHIFT CAUSE LOSS OF MANTISSA?
TDZA A2,A2 ; YES - SAVE A LOT OF WORK
ASHC A1,-200(A3) ; SHIFT OUT INTEGER PART
ANDI A1,1 ; SET ODD/EVEN FLAG FOR N
LSH A2,-10
TLO A2,200000 ; AND FIX UP NEW EXPONENT
FSBRI A2,200400 ; SUBTRACT 0.5 TO GET Y
TAN1: MOVE A3,A2 ; SAVE Y
FMPR A2,A2 ; SAVE Y^2
MOVEI A5,3
MOVE A4,TAN7
TAN2: FMPR A4,A2
FADR A4,TAN6(A5)
SOJGE A5,TAN2
FMPR A4,A3 ; FORM -P(Y)
MOVN A2,A2
FADRI A2,201400 ; FORM 1 - Y^2
JUMPN A1,TAN3 ; N ODD?
EXCH A4,A2 ; YES - EXCHANGE OPERANDS
MOVN A0,A0 ; AND INVERT ARGUMENT SIGN
TAN3: FDVR A4,A2 ; FORM FINAL RESULT
JFOV TAN5 ; OVERFLOW IS FATAL
EXCH A0,A4 ; LOAD UP RESULT
JUMPGE A4,TAN4 ; SHOULD IT BE NEGATIVE?
MOVN A0,A0 ; YES - NEGATE IT
TAN4: POPJ SP,0
TAN5: LIBERR 4,@(SP)
TAN6: XWD 201622,077325 ; PI/2
XWD 600342,340621 ; PI/2*((PI/2)^2/3 - 1)
XWD 604353,774024 ; (PI/2)^3*((PI/2)^2*2/15 - 1/3)
XWD 610120,631722 ; (PI/2)^5*((PI/2)^2*17/315 - 2/15)
TAN7: XWD 613217,113617 ; (PI/2)^7*((PI/2)^2*62/2835 - 17/315)
LIT
PRGEND
TITLE DSINH - DUMMY BODY FOR SINH
; REAL PROCEDURE SINH(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<211>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL ALIAS)
EXTLAB<111>
LABEL(211): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(111) ; CALL SINH
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE SINH - SINGLE PRECISION SINH ROUTINE
; TRANSCRIBED FROM LIB40 V.27/KK/DMN
; METHOD:
;
; IF ABS(X) < 0.1, SINH(X) = X + X^3/6 + X^5/120
;
; IF 0.1 <= ABS(X) < 88.029, SINH(X) = (EXP(X) - EXP(-X))/2
;
; IF ABS(X) >= 88.029, SINH(X) = SIGN(X)*EXP(ABS(X) - LN(2))
;
; EXP(-X) IS 1/EXP(X)
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
EXTLAB<104>
STDENT(111,SINH)
MOVM A1,A0 ; SAVE ABS(X)
CAML A1,[
XWD 175631,463146] ; < 0.1?
JRST SINH1 ; NO
FMPR A1,A1 ; YES - FORM X^2
MOVE A2,A1 ; AND SAVE IT
FDVRI A1,207740
FADR A1,[
XWD 176525,252525]
FMPR A1,A2
FADRI A1,201400
FMPR A0,A1 ; FORM X + X^3/6 + X^5/120
POPJ SP,0
SINH1: CAML A1,[
XWD 207540,074636] ; < 88.029?
JRST SINH2 ; NO
PUSHJ SP,LABEL(104) ; YES - CALCULATE EXP(X)
MOVSI A1,576400
FDVR A1,A0 ; CALCULATE -EXP(-X)
FADR A0,A1
FSC A0,-1 ; FORM SINH(X)
POPJ SP,0
SINH2: PUSH SP,A0 ; SAVE X
MOVE A0,A1
FSBR A0,[
XWD 200542,710300] ; FORM ABS(X) - LN(2)
PUSHJ SP,LABEL(104) ; AND CALL EXP
POP SP,A1 ; RESTORE X
JUMPGE A1,SINH3 ; POSITIVE?
MOVN A0,A0 ; NO - NEGATE RESULT
SINH3: POPJ SP,0
LIT
PRGEND
TITLE DCOSH - DUMMY BODY FOR COSH
; REAL PROCEDURE COSH(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<212>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<112>
LABEL(212): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(112) ; CALL COSH
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE COSH - SINGLE PRECISION COSH ROUTINE
; TRANSCRIBED FROM LIB40 V27/EY/KK/DMN
; METHOD:
;
; IF ABS(X) < 88.029, COSH(X) = (EXP(X) + EXP(-X))/2
;
; IF 88.029 <= ABS(X) < 88.029 + LN(2), COSH(X) = EXP(ABS(X) + LN(2))
;
; EXP(-X) IS 1/EXP(X)
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
EXTLAB<104>
STDENT(112,COSH)
MOVM A0,A0 ; FORM ABS(X)
CAML A0,COSH2 ; < 88.029?
JRST COSH1 ; NO
PUSHJ SP,LABEL(104) ; YES - CALCULATE EXP(X)
MOVSI A1,201400
FDVR A1,A0 ; CALCULATE EXP(-X)
FADR A0,A1
FSC A0,-1 ; FORM COSH(X)
POPJ SP,0
COSH1: FSBR A0,[
XWD 200542,710300]
CAML A0,COSH2 ; < 88.029 + LN(2)?
LIBERR 4,@(SP) ; NO - COMPLAIN
JRST LABEL(104) ; YES - LET EXP DO THE WORK
COSH2: XWD 207540,074635 ; 88.029
LIT
PRGEND
TITLE DTANH - DUMMY BODY FOR TANH
; REAL PROCEDURE TANH(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<213>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<113>
LABEL(213): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(113) ; CALL TANH
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE TANH - SINGLE PRECISION TANH ROUTINE
; TRANSCRIBED FROM LIB40 V.21/EY/KK
; METHOD:
;
; IF ABS(X) < 0.00034, TANH(X) = X
;
; IF 0.00034 <= ABS(X) < 0.17, TANH(X) = F/(K1 + F^2*(K2 + K3
;
; /(K4 + F^2)))
;
; WHERE F = 4*LOG2(E)*X
;
; IF 0.17 <= ABS(X) < 12.0, TANH(X) = (1 - 2/(1 + EXP(2*X))*SIGN(X)
;
; IF X >= 12.0, TANH(X) = SIGN(X)
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
EXTLAB<104>
STDENT(113,TANH)
MOVM A5,A0 ; MAGNITUDE OF ARGUMENT
CAMGE A5,[
XWD 165544,410070] ; < 0.00034?
JRST TANH1 ; YES - TANH(X) = X
CAML A5,[
XWD 204600,000000] ; ABS(X) >= 12.0?
JRST TANH3 ; YES - TANH(X) = SIGN(X)
CAMGE A5,[
XWD 176534,121727] ; ABS(X) >= 0.17?
JRST TANH2 ; NO
FSC A0,1
PUSHJ SP,LABEL(104) ; CALCULATE EXP(2*X)
FADRI A0,201400
MOVSI A1,575400
FDVRM A1,A0
FADRI A0,201400 ; 1 - 2/(1 + EXP(2*ABS(X)))
TANH1: POPJ SP,0
TANH2: FMPR A0,TANH4 ; F = 4*LOG2(E)*X
MOVE A1,A0
FMPR A1,A1
MOVE A2,A1 ; FORM AND TAKE COPY OF F^2
FADR A1,TANH7 ; ADD K4
MOVE A5,TANH6
FDVR A5,A1 ; K3/(K4 + F^2)
FADR A5,TANH5 ; + K2
FMPR A5,A2 ; *F^2
FADR A5,TANH4 ; + K1
TANH3: FDVR A0,A5
POPJ SP,0
TANH4: XWD 203561,250731 ; K1 = 4*LOG2(E)
TANH5: XWD 173433,723376 ; K2 = 1.73286795&-1
TANH6: XWD 204704,333567 ; K3 = 1.41384514
TANH7: XWD 211535,527022 ; K4 = 3.49669988&2
LIT
PRGEND
TITLE DEXP - DUMMY BODY FOR EXP
; REAL PROCEDURE EXP(X); VALUE X; REAL X;
.EXIT=1
.X=3
SEARCH ALGPRM,ALGSYS
%ENTER<204>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<104>
LABEL(204): JSP AX,PARAM
Z
XWD 0,3
XWD $PRO!$R!$SIM,2
XWD $VAR!$R!$FOV,.X
MOVE A0,.X(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(104) ; CALL EXP
MOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE EXP - SINGLE PRECISION EXPONENTIATION ROUTINE
; REWRITE OF LIB40 V.21/EY/KK/DMN
; METHOD:
;
; IF X < -89.416, EXP(X) = 0
;
; IF -89.416 <= X < 88.029:
;
; X = (N+Y)*LN(2), WHERE N IS AN INTEGER, AND 0 <= Y < 1
;
; EXP(X) = 2^(N+Y) = 2^N*2^Y
;
; WHERE 2^Y = 2*(0.5 + Y/(K1 - Y + K2*Y^2 + K3/(K4 + Y^2))
;
; IS DERIVED FROM THE PADE (4,4) APPROXIMATION
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0
SEARCH ALGPRM,ALGSYS
STDENT(104,EXP)
CAMGE A0,[
XWD 570232,254037] ; X < -89.416?
JRST EXP1 ; YES - QUICK EXIT
CAML A0,[
XWD 207540,074636] ; X >= 88.029?
LIBERR 2,@(SP) ; YES - COMPLAIN
MULI A0,400 ; SEPARATE EXPONENT FROM MANTISSA
MOVE 3,A0
TSC A3,A3 ; GET POSITIVE EXPONENT
MUL A1,[
XWD 270524,354513] ; MULTIPLY MANTISSA BY LOG2(E)
ASHC A1,-242(A3) ; SEPARATE INTEGER PART
JUMPGE A1,.+2
ADDI A1,1 ; ADJUST IF NEGATIVE FRACTION
JUMPG A2,EXP6
TRNE A2,000377 ; IF NECESSARY ...
ADDI A2,200 ; DO A LITTLE ROUNDING
EXP6: ASH A2,-10
TLC A2,200000 ; FORM Y
FADRI A2,000000 ; NORMALIZE
MOVE A0,A2 ; SAVE A COPY
FMPR A2,A2 ; AND FORM Y^2
MOVE A3,A2
FADR A3,EXP5 ; K4 + Y^2
MOVE A4,EXP4
FDVR A4,A3 ; K3/(K4 + Y^2)
FMPR A2,EXP3
FADR A2,A4
FADR A2,EXP2
FSBR A2,A0 ; K1 - Y + K2*Y^2 + K3/(K4 + Y^2)
FDVR A0,A2
FADRI A0,200400 ; 0.5 + Y/(K1 - Y + K2*Y^2 + K3/(K4 + Y^2))
FSC A0,1(A1) ; MULTIPLY BY 2^(N+1)
POPJ SP,0
EXP1: MOVEI A0,0
POPJ SP,0
EXP2: XWD 204476,430062 ; K1 = 9.95459578
EXP3: XWD 174433,723400 ; K2 = 3.46573590&-2
EXP4: XWD 565313,007063 ; K3 = -6.17972270&2
EXP5: XWD 207535,527022 ; K4 = 8.74174972&1
LIT
PRGEND
TITLE DLSIN - DUMMY BODY FOR LSIN
; LONG REAL PROCEDURE LSIN(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<214>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<114>
LABEL(214): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(114) ; CALL LSIN
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE DLCOS - DUMMY BODY FOR LCOS
; LONG REAL PROCEDURE LCOS(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<215>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<115>
LABEL(215): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(115) ; CALL LCOS
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LSIN /LCOS - DOUBLE PRECISION SINE/COSINE ROUTINES
; TRANSCRIBED FROM LIB40 V.022/.020/.005/KK/TWE
; METHOD: SEE SCIENCE LIBRARY AND FORTRAN UTILITY SUBPROGRAMS
; MANUAL
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0,A1
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
STDENT(115,LCOS)
DFAD A0,LSIN22 ; COS(X)=SIN(PI/2+X), LEAVE RESULT IN A0
JRST LSIN0
STDENT(114,LSIN)
LSIN0: JUMPE A0,LSIN8 ; ARGUMENT OF ZERO?
SETZB A6,A12 ; SET FLAG FOR POSITIVE ARGUMENT
JUMPGE A0,LSIN1 ; IS ARGUMENT POSITIVE?
MOVNI A12,1 ; NO, CHANGE FLAG
DMOVN A0,A0 ; NEGATE THE ARGUMENT
LSIN1: DMOVE A7,A0
DFDV A0,LSIN22 ; CALCULATE X/(PI/2)
CAML A0,LSIN21 ; X < PI/2?
JRST LSIN10 ; NO, REDUCE IT
CAML A0,[
XWD 200400,000000] ; X >= PI/4
MOVEI A6,1 ; YES, 2ND OCTANT
LSIN2: DMOVE A0,A7
LSIN3: TRNE A6,4 ; QUADRANTS 3 OR 4?
SETCA A12,0 ; YES, SINE IS NEGATIVE
JUMPE A6,LSIN5 ; X < PI/4
TRNE A6,1 ; NO, GET INDEX INTO QUADRANT TABLE
ADDI A6,1 ; ...
DFAD A0,LSIN20-2(A6) ; MAKE -PI/4 <= X < PI/4
JUMPGE A0,LSIN4
DMOVN A0,A0 ; TAKE ABSOLUTE VALUE
LSIN4: DMOVE A7,A0
LSIN5: TRZ A6,777775 ; LEAVE ONLY OCTANT BIT
HRRZ A11,A6 ; 0 FOR SINE SERIES, 2 FOR COSINE
CAMG A0,[
XWD 147471,421605] ; X < SQRT(6)*2^(-27)?
JRST LSIN9 ; YES, THEN SIN(X)=X
DFMP A0,A7 ; CALCULATE X^2
DMOVE A3,LSIN11(A6) ; INITIALIZE PARTIAL SUM
MOVEI A6,LSIN12(A6) ; TURN OCTANT POINTER INTO TABLE ADDRESS
LSIN6: DFMP A3,A0 ; MULTIPLY PARTIAL SUM BY X^2
DFAD A3,0(A6) ; ADD NEXT CONSTANT TO PARTIAL SUM
ADDI A6,4 ; MOVE POINTER TO NEXT CONSTANT
CAIG A6,LSIN19 ; DONE?
JRST LSIN6 ; NO, LOOP BACK FOR MORE OF SERIES
DFMP A0,A3 ; YES, ONE MORE MULTIPLY
DFAD A0,LSIN21 ; ADD 1.0 INTO SUM
JUMPN A11,LSIN7 ; IS THIS COSINE SERIES?
DFMP A0,A7 ; NO, MULTIPLY BY X, THIS IS SIN
LSIN7: JUMPE A12,LSIN8 ; NEGATE RESULT?
DMOVN A0,A0 ; YES
LSIN8: POPJ SP,0 ; EXIT
LSIN9: JUMPE A6,LSIN7 ; CALCULATING COSINE?
DMOVE A0,LSIN21 ; YES, COS(X)=1.0
JRST LSIN7
LSIN10: MOVE A3,A0 ; SAVE QUADRANT NUMBER
LDB A6,[
POINT 8,A0,8] ; GET EXPONENT
LSH A1,1 ;
TLZ A0,777000 ; DITTO HIGH EXPONENT
LSHC A0,-202(A6) ; MAKE ARGUMENT MODULO 2 PI
LDB A6,[
POINT 3,A0,11] ; GET QUADRANT AND OCTANT BITS
CAMGE A3,[
XWD 203400,000000] ; IS NON-REDUCED ARGUMENT OK?
JRST LSIN2 ; YES, SAVE THE DFMP INACCURACIES
TLZ A0,777000 ; MAKE WAY FOR EXPONENT
TLO A0,202000
LSH A1,-1
DFAD A0,[EXP 0,0]
DFMP A0,LSIN22 ; CHANGE MAKE TO RADIANS (MOD 2 PI)
DMOVE A7,A0 ; TEMPORARY X
JRST LSIN3 ; GO CHANGE ARGUMENT TO 1ST OCTANT
LSIN11: EXP 120625130734,014126512326 ; 1/17!=.28114572543455207632&&-14
EXP 124656376371,314734037043 ; 1/16!=.47794773323873852974&&-13
LSIN12: EXP 647121401406,463043740735 ; -1/15!=-.76471637318198164759&&-12
EXP 643154321325,717701542677 ; -1/14! =-.11470745597729724714&&-10
LSIN13: EXP 140541110604,352066411370 ; 1/13!=.16059043836821614599&&-9
EXP 144436733073,376154227552 ; 1/12!=.20876756987868098979&&-8
LSIN14: EXP 630121467246,402535434340 ; -1/11!=-.25052108385441718775&&-7
EXP 624330066022,441660243433 ; -1/10!=-.27557319223985890653&&-6
LSIN15: EXP 156561674351,125543463437 ; 1/9!=.27557319223985890653&&-5
EXP 161640064006,200320032003 ; 1/8!=.24801587301587301587&&-4
LSIN16: EXP 613137713771,577457745775 ; -1/7!=-.19841269841269841270&&-3
EXP 610223722372,517511751175 ; -1/6!=-.1388888888888888889&&-2
LSIN17: EXP 172421042104,104210421042 ; 1/5!=.00833333333333333333333
EXP 174525252525,125252525253 ; 1/4!=.041666666666666666667
LSIN18: EXP 601252525252,652525252526 ; -1/3!=-0.16666666666666666667
LSIN19: EXP 577400000000,000000000000 ; -1/2!=-0.50000000000000000000
PIOTLO=021026430215 ; LOW HALF OF PI/2 FOR KI10
LSIN20: EXP 576155700452,-PIOTLO ; -PI/2
EXP 575155700452,-PIOTLO ; -PI
574322320340 ; -3*PI/2
463157055627
EXP 574155700452,-PIOTLO ; -2*PI
LSIN21: EXP 201400000000,000000000000 ; 1.0
LSIN22: EXP 201622077325,PIOTLO ; PI/2
LIT
PRGEND
TITLE DLARCTAN - DUMMY BODY FOR LARCTAN
; LONG REAL PROCEDURE LARCTAN(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<216>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<116>
LABEL(216): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(116) ; CALL LARCTAN
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LARCTAN - DOUBLE PRECISION ARCTANGENT ROUTINE
; TRANSCRIBED FROM LIB40 V.022/.020/.005/KK/TWE
; METHOD:
; THIS ROUTINE CALCULATES THE ACTANGENT OF A DOUBLE PRECISION
; ARGUMENT ACCORDING TO THE ALGORITHM
; ARCTAN(X) = LAMBDA*X/(Z+LTN11+LTN12/(Z+LTN13+LTN14/(Z+LTN15+LTN16/(Z+LTN17))))
; FOR X > 1.0, THE IDENTITY
; ARCTAN(X) = PI/2 - ARCTAN(1/X)
; IS USED. FOR 0.5 < X < 1.0, THE IDENTITY
; ARCTAN(X) = ARCTAN(1/2) + ARCTAN(2X-1/X+2)
; IS USED.
; FOR X < SQRT(3)*2^(-27), ARCTAN(X) = X IS USED
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0,A1
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
;
Edit(155); Improve accuracy of LARCTAN for x in neighbourhood of 1.0.
;
STDENT(116,LARCTAN)
JUMPE A0,LTN9 ; ARGUMENT = 0?
HLLZ A6,A0 ; LH(A6)=SGN(A0), RH(A6) = 0
TLZ A6,377777 ; [E155]
JUMPGE A0,LTN1 ; IS THE ARGUMENT POSITIVE?
DMOVN A0,A0 ; NO, NEGATE IT
LTN1: MOVSI A3,201400 ; GET DOUBLE PRECISION 1.0
MOVEI A4,0 ; 0 LOW PART
CAMN A0,A3 ; IS HIGH ORDER EQUAL TO 1.0?
JUMPE A1,LTN2 ; YES, IS LOW ORDER ZERO?
CAMGE A0,A3 ; NO, IS ARGUMENT > 1.0?
JRST LTN2 ; NO
TLC A6,400000 ; COMPLEMENT FINAL SIGN BIT, GET 1/X
TLO A6,1 ; [E155]
DFDV A3,A0
DMOVE A0,A3
LTN2: DMOVE A10,A0
CAMGE A0,[0.236] ; IS ARGUMENT >= SQRT(5)-2 ?
JRST LTN3 ; NO, PROCEED WITH ALGORITHM
; CALCULATE X+2
DFAD A0,LTN21
EXCH A0,A10 ; GET X, SAVE X+2
EXCH A1,A11 ; ...
FSC A0,1 ; CALCULATE 2X
; CALCULATE 2X-1
DFAD A0,LTN20
; (2X-1)/(X+2) WITH RESULTS IN A0,A1
DFDV A0,A10
AOJA A6,LTN2 ; [E155]
LTN3: MOVM A3,A0
CAMGE A3,LTN23 ; CAN ATAN(X)=X?
JRST LTN6 ; YES
DFMP A0,A10 ; CALCULATE X^2
DMOVE A12,A0
DMOVE A0,LTN17 ; INITIALIZE CONTINUED FRACTION
; COMPARISON WITH LTN17
MOVEI A7,LTN17 ; INITIALIZE POINTER TO NUMBER TABLE
JRST LTN5 ; ENTER LOOP
LTN4: DFAD A0,0(A7) ; ADD LTN13
LTN5: DFAD A0,A12 ; ADD X^2
DMOVE A3,-2(A7) ; GET LTN16 (OR LTN12)
DFDV A3,A0
DFAD A3,-4(A7) ; ADD LTN15 (OR LTN11)
DFAD A3,A12 ; ADD X^2
DMOVE A0,-6(A7) ; GET LTN14 (OR LAMBDA)
DFDV A0,A3
SUBI A7,10 ; DECREMENT TABLE POINTER
CAILE A7,LTN10 ; FINISHED?
JRST LTN4 ; NO, DO IT LAST TIME
DFMP A0,A10 ; MULTIPLY BY X
LTN6: TRNN A6,-1 ; [E155]
JRST LTN7 ; [E155]
DFAD A0,LTN18 ; [E155]
SOJA A6,LTN6 ; [E155]
LTN7: TLNE A6,1 ; [E155]
DFAD A0,LTN22 ; [E155]
JUMPGE A6,LTN9 ; NEGATE RESULT?
DMOVN A0,A0 ; YES
LTN9: POPJ SP,0 ; EXIT
LTN10: EXP 204613772770,017027645561 ; 12.37469 38775 51020 40816
LTN11: EXP 205644272446,121335250615 ; 26.27277 52490 26980 67155
LTN12: EXP 570276502107,437176661671 ; -80.34270 56102 16599 70467
LTN13: EXP 203627237361,165414142742 ; 6.36424 16870 04411 34492
LTN14: EXP 576316772502,512470127251 ; -1.19144 72238 50426 48905
LTN15: EXP 202415301602,015271031674 ; 2.10451 89515 40978 95180
LTN16: EXP 602277106546,717167531241 ; -0.07833 54278 56532 11777
LTN17: EXP 201502125320,370207664057 ; 1.25846 41124 27629 031727
LTN18: EXP 177732614701,130335517321 ; ATAN(1/2)
LTN19: XWD 200400,000000 ; 0.5
LTN20: EXP 576400000000,000000000000 ; -1.0
LTN21: EXP 202400000000,000000000000 ; EXP 2.0
LTN22: EXP 576155700452,756751347563 ; -PI/2
LTN23: XWD 146673,317272 ; SQRT(3)*2^(-27)
LIT
PRGEND
TITLE DLSQRT - DUMMY BODY FOR LSQRT
; LONG REAL PROCEDURE LSQRT(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<217>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<117>
LABEL(217): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(117) ; CALL SQRT
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LSQRT - DOUBLE PRECISION SQUARE ROOT ROUTINE
; TRANSCRIBED FROM LIB40 V.022/.020/.005/KK/TWE
; METHOD:
; THIS ROUTINE CALCULATES THE SQUARE ROOT OF A DOUBLE PRECISION
; ARGUMENT BY DOING A LINEAR SINGLE PRECISION APPROXIMATION ON
; THE HIGH ORDER WORD, THEN TWO DOUBLE PRECISION ITERATIONS OF
; NEWTONS METHOD. THIS SHOULD GENERATE A RESULT ACCURATE TO
; 20 SIGNIFICANT DECIMAL DIGITS. THE ALGORITHM IS AS FOLLOWS
; X = (2^(2N))*F, WHERE 1/2 < F < 1
; HENCE SQRT(X) = 2^N*SQRT(F)
; THE LINEAR APPROXIMATION IS OF THE FORM
; SQRT(F) = LSQ3 - LSQ4/(LSQ5+F-LSQ6/(LSQ7+F))
; WHERE THE CONSTANTS LSQ3,LSQ4,LSQ5,LSQ6, AND LSQ7 HAVE THE FOLLOWING
; VALUES
; CONSTANT VALUE WHEN 0.25<F<0.50 VALUE WHEN 0.50<F<1.0
; LSQ3 (5/14)*SQRT(70) (5/7)*SQRT(35)
; LSQ4 (50/49)*SQRT(70) (200/49)*SQRT(35)
; LSQ5 47/14 47/7
; LSQ6 4/49 16/49
; LSQ7 3/14 3/7
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0,A1
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
STDENT(117,LSQRT)
JUMPE A0,LSQ2 ; ARGUMENT OF ZERO?
JUMPGE A0,.+2 ; IS ARGUMENT POSITIVE?
LIBERR 0,@(SP) ; NO, COMPLAIN
MOVE A5,A0 ; GET SPARE COPY OF HIGH ORDER
LSH A5,-33 ; GET RID OF FRACTION BITS
SUBI A5,201 ; GET RID OF THE BASE 200 PART OF
; EXPONENT. EXTRA 1 IS A FUDGE.
ROT A5,-1 ; CUT EXPONENT IN HALF, SAVE EXTRA
; BIT FOR LATER USE AS INDEX REG.
HRRZ A11,A5 ; SAVE REDUCED EXPONENT FOR SCALING
LSH A5,-43 ; BRING BIT BACK - IF 0, THEN
; 1/4<A5<1/2,OTHERWISE 1/2<A5<1.
TLZ A0,777000 ; WIPE OUT EXPONENT BITS IN ARG.
FSC A0,177(A5) ; RESET IT TO EITHER 177 OR 200
MOVE A3,A0 ; PICK UP ANOTHER COPY OF NEW FRAC.
FADR A3,LSQ7(A5) ; FORM LSQ7+F
MOVN A2,LSQ6(A5) ; PICK UP -LSQ6
FDVR A2,A3 ; CALCULATE -LSQ6/(LSQ7+F)
FADR A2,LSQ5(A5) ; GET LSQ5-LSQ6/(LSQ7+F)
FADR A2,A0 ; CALCULATE F+LSQ5-LSQ6/(LSQ7+F)
MOVN A3,LSQ4(A5) ; PICK UP -LSQ4
FDVR A3,A2 ; GET -LSQ4/(F+LSQ5-LSQ6/(LSQ7+F))
FADR A3,LSQ3(A5) ; GET FINAL FIRST APPROXIMATION
MOVEI A4,0 ; LOW HALF OF 1ST APPROX. IS 0
DMOVE A7,A0 ; SAVE LSQRT ARGUMENT
DFDV A0,A3 ; GET N/X0
DFAD A0,A3 ; X0+N/X0
FSC A0,-1 ; X1=.5*(X0+N/X0)
EXCH A0,A7 ; GET ARGUMENT INTO AC, SAVE X1
EXCH A1,A10 ; ...
; N/X1
DFDV A0,A7
; X1+N/X1
DFAD A0,A7
LSQ1: FSC A0,(A11) ; SCALE RESULTS FOR ANSWER
LSQ2: POPJ SP,0 ; EXIT
LSQ3: XWD 202576,362203 ; 2.98807152
XWD 203416,346045 ; 4.225771271
LSQ4: XWD 204421,143713 ; 8.537347194
XWD 205602,266310 ; 24.14726441
LSQ5: XWD 202655,555556 ; 3.357142857
XWD 203655,555556 ; 6.7142857143
LSQ6: XWD 175516,274052 ; 0.0816326531
XWD 177516,274052 ; 0.326530612
LSQ7: XWD 176666,666667 ; 0.2142857143
XWD 177666,666667 ; 0.4285714286
LIT
PRGEND
TITLE DLEXP - DUMMY BODY FOR LEXP
; LONG REAL PROCEDURE LEXP(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<220>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<120>
LABEL(220): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(120) ; CALL LEXP
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LEXP - DOUBLE PRECISION EXPONENTIAL FUNCTION
; [240] OLD VERSION WAS VERY MESSY AND INACCURATE IN SOME CASES.
EDIT (240)
; THIS ROUTINE USES THE FOLLOWING ALGORITHM:
;
; IF X < -88.028, RESULT = 0
; IF X > 88.028, AN ERROR RESULTS
; IF X = 0.0, RESULT = 1
;
; ELSE
; THE ARGUMENT REDUCTION IS:
; X1 = [X], THE GREATEST INTEGER IN X
; X2 = X - X1
; N = THE NEAREST INTEGER TO X/LN(2)
;
; THE REDUCED ARGUMENT IS
;
; G = ((X1 - N*C1)+X2)-N*C2
; WHERE C1 = .543 (OCTAL),
; AND C2 IS GIVEN BELOW
;
; THE CALCULATION IS:
;
; EXP = R(G)*2**N
;
; WHERE R(G) = 0.5 + G*P/(Q - G*P)
; P = ((((P2*G**2)+P1)*G**2)+P0)*G**2
; Q = (((((Q3*G**2)+Q2)*G**2)+Q1)*G**2)+Q0
;
; P0, P1, P2, Q0, Q1, Q2, AND Q3 ARE GIVEN BELOW AS
; XP0, XP1, XP2, XQ0, XQ1, XQ2, AND XQ3 .
;
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0,A1
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
;
SEARCH ALGPRM,ALGSYS
STDENT (120,LEXP) ; [240]
JUMPE A0,[ ; [240]
MOVSI A0,(1.0) ; [240] LOAD 1.0 FOR ARGUMENT OF ZERO
JRST LEXP3 ; [240] AND RETURN TO CALLING ROUTINE
] ; [240]
MOVM A2,A0 ; [240] GET MAGNITUDE OF ARGUMENT
CAML A2,LEXP4 ; [240] WITHIN LIMITS?
JRST [ ; [240] NO, GO TAKE A CLOSER LOOK
MOVE A3,A0 ; [240] TAKE COPY OF HIGH ORDER WORD
SETZB A0,A1 ; [240] SET ARG. = 0
JUMPL A3,LEXP3 ; [240] EXIT IF ARG. WAS < 0
LIBERR 2,@(SP) ; [240] ELSE ERROR
] ; [240]
;****************************************************************************
; ; [240] BEGINNING OF MAJOR CODE CHANGE TO LEXP
;****************************************************************************
PUSH SP,A5 ; SAVE A5 BEFORE USING IT
DMOVE A2,A0 ; PUT A COPY OF ARG IN A2,A3
DFMP A2,LEXP5 ; CALCULATE ARG * 1/LN(2)
FIXR A2,A2 ; GET NEAREST INTEGER
FLTR A2,A2 ; FLOAT IT
MOVEI A3,0 ; CLEAR SECOND WORD OF A2, A3
FIX A4,A0 ; GET FIXED POINT HIGH-ORDER ARG. IN A4
FLTR A4,A4 ; FLOAT IT
MOVEI A5,0 ; CLEAR SECOND WORD OF A4, A5
DFSB A0,A4 ; CALCULATE X2
MOVE A7,A2 ; SAVE EXPONENT SCALING FACTOR FOR LATER
DFMP A2,C1 ; CALCULATE N*C1
DFAD A4,A2 ; ADD X1
DFAD A4,A0 ; ADD X2
MOVE A2,A7 ; GET EXPONENT SCALING FACTOR BACK
MOVEI A3,0 ; CLEAR LOW ORDER WORD OF A2, A3
DFMP A2,C2 ; CALCULATE N*C2
DFAD A4,A2 ; CALCULATE (N*C2)+X1+(N*C1)+X2
DMOVE A0,A4 ; MOVE ANSWER TO A0
MOVM A2,A4 ; GET ABSOLUTE VALUE IN A2
CAML A2,CM2 ; IS REDUCED ARG < 2^-32?
JRST LEXPOK ; NO, JUMP AHEAD
DFAD A0,DBLONE ; YES, ADD 1.0 TO G
FSC A0,-1 ; DIVIDE IT BY 2.0
JRST LDONE ; ALL DONE - JUMP AHEAD
LEXPOK: DFMP A4,A4 ; SQUARE A4
DMOVE A2,A4 ; SAVE IT
DFMP A4,XP2 ; AND MULTIPLY IT BY XP2
DFAD A4,XP1 ; ADD XP1
DFMP A4,A2 ; MULTIPLY IT BY Z
DFAD A4,XP0 ; ADD XP0
DFMP A0,A4 ; MULTIPLY BY G, ANSWER IN A0, A1
DMOVE A4,A2 ; PUT ANSWER IN A4, A5
DFMP A4,XQ3 ; MULTIPLY BY Z
DFAD A4,XQ2 ; ADD XQ2
DFMP A4,A2 ; MULTILPLY BY Z
DFAD A4,XQ1 ; ADD XQ1
DFMP A4,A2 ; MULTIPLY BY Z
DFAD A4,XQ0 ; ADD XQ0
DFSB A4,A0 ; CALCULATE XQ - G*XP
DFDV A0,A4 ; CALCULATE (G*XP)/(XQ-G*XP)
DFAD A0,XQ0 ; ADD 0.5
LDONE: FIX A7,A7 ; GET FIXED POINT SCALING VALUE
ADDI A7,1 ; ADD ONE
FSC A0,(A7) ; ADJUST FINAL ANSWER IN A0, A1
POP SP,A5 ; RESTORE A5
LEXP3: POPJ SP, ; RETURN TO CALLING ROUTINE
LEXP4: XWD 207540,071260 ; 88.028
LEXP5: EXP 201561250731,112701376065 ; 1.44269504088896341=1/LN(2)
DBLONE: EXP 201400000000,000000000000 ; 1.0&&0
CM2: EXP 141400000000,000000000000 ; 2^-32
C1: EXP 577235000000,000000000000 ; -0.693359375&&0
C2: EXP 164675002027,030206250331 ; 2.12194440054690583&&-4
XP0: EXP 177400000000,000000000000 ; 0.250&&0
XP1: EXP 171760351374,212411245446 ; 0.757531801594227767&&-2
XP2: EXP 162410550412,271511036101 ; 0.315551927656846464&&-4
XQ0: EXP 200400000000,000000000000 ; 0.5&&0
XQ1: EXP 174721345024,167754776545 ; 0.568173026985512218&&-1
XQ2: EXP 166512741427,012152337316 ; 0.631218943743985036&&-3
XQ3: EXP 154623154303,071202125117 ; 0.751040283998700461&&-6
PRGEND
;****************************************************************************
; ; [240] END OF MAJOR CODE CHANGE TO LEXP
;****************************************************************************
TITLE DLLN - DUMMY BODY FOR LLN
; LONG REAL PROCEDURE LLN(D); VALUE D; LONG REAL D;
.EXIT=1
.D=4
SEARCH ALGPRM,ALGSYS
%ENTER<221>
SALL
EXTERNAL %ALGDR
%SUBTTL(ALGLIB,ALGOL LIBRARY)
EXTLAB<121>
LABEL(221): JSP AX,PARAM
Z
XWD 0,5
XWD $PRO!$LR!$SIM,2
XWD $VAR!$LR!$FOV,.D
DMOVE A0,.D(DL) ; GET ARGUMENT
PUSHJ SP,LABEL(121) ; CALL LLN
DMOVEM A0,.EXIT+1(DL) ; STORE RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LLN - DOUBLE PRECISION LOGARITHM FUNCTION
; TRANSCRIBED FROM LIB40 V.022/.020/.005/KK/TWE
; METHOD:
; THIS PROGRAM CALCULATES THE LOGARITHM OF A DOUBLE PRECISION
; ARGUMENT. THE ALGORITHM USED IS DESCRIBED ON PAGES 29-30 OF
; RALSTON AND WILF, "MATHEMATICAL METHODS FOR DIGITAL COMPUTERS".
; THE ARGUMENT X IS WRITTEN AS
; X = (2^N)*F WHERE 1/2 < F < 1
; THEN LN(X) = (N*LN(2)) + LN(F)
; F IS REDUCED BY FIXED POINT MULTIPLICATION BY NOT MORE THAN
; THREE CONSTANTS. THIS YIELDS
; 0 < T = K1*K2*K3*F - 1.0 < (2^(-7))/5
; NOTE THAT NOT ALL THE K1,K2,K3 NEED BE INCLUDED IN THE PRODUCT.
; FINALLY,
; LN(F) = LN(1+T) - LN(K1) - LN(K2) - LN(K3)
; LN(1+T) IS CALCULATED AS A TAYLOR SERIES IN T.
SEARCH ALGPRM,ALGSYS
; ON ENTRY:
; THE ARGUMENT (X) IS IN A0,A1
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
STDENT(121,LLN)
JUMPG A0,.+2 ; ARGUMENT <= 0?
LIBERR 1,@(SP) ; YES, COMPLAIN
CAMN A0,LLN17 ; X PRECISELY 1.0?
JUMPE A1,[
MOVEI A0,0
JRST LLN5] ; YES, RETURN ZERO
LLN1: LDB A3,[
POINT 8,A0,8] ; NO, PICK UP EXPONENT FROM HIGH ORDER
SUBI A3,200 ; GET EXPONENT EXCESS 200
FSC A3,233 ; MAKE FLOATING POINT NUMBER
MOVEI A4,0 ; SET UP LOW HALF
; CALCULATE N*LN(2)
DFMP A3,LLN8
DMOVE A7,A3
TLZ A0,777000 ; MASK OUT EXPONENT
ASHC A0,10 ; NORMALIZE FRACTION TO BIT 1
SETZB A3,A4 ; INITIALIZE REDUCTION CONSTANT TO 0
LLN2: LDB A6,[
POINT 3,A0,4] ; GET HIGH 3 BITS BELOW 1/2
MUL A1,LLN7(A6) ; FIXED POINT MULTIPLY FOR LOW HALF
MOVE A2,A1 ; SAVE HIGH HALF OF LOW PRODUCT
; (LOW HALF IS ALL 0'S, THROW IT AWAY)
MUL A0,LLN7(A6) ; MULTIPLY HIGH ORDER, TOO
TLO A1,400000 ; SET BIT 0, TO AVOID OVERFLOW
ADD A1,A2 ; COMBINE RESULTS OF MULTIPLY
TLZN A1,400000 ; CLEAR BIT 0, WAS THERE OVERFLOW?
ADDI A0,1 ; YES, PROPOGATE CARRY
ASH A6,1 ; TURN BITS INTO D.P. POINTER
DFAD A3,LLN6(A6)
TLZE A0,200000 ; IS THE PRODUCT >= 1.0?
JRST LLN3 ; YES
ASHC A0,1 ; NO, GET RID OF EXTRANEOUS ZERO
JRST LLN2 ; TRY ANOTHER MULTIPLICATION
LLN3: ASHC A0,-7 ; MAKE ROOM FOR THE EXPONENT
TLC A0,200000 ; INSERT EXPONENT
DFAD A0,LLN18 ; NORMALIZE
DMOVN A3,A3 ; NEGATE LOG OF MAGIC NUMBERS
; AND ADD INTO FINAL SUMMATION
DFAD A3,A7
DMOVE A7,A3
DMOVE A3,LLN9 ; PICK UP CONSTANT TO START
MOVEI A6,LLN10 ; INITIALIZE TABLE POINTER AT LLN10
LLN4: DFMP A3,A0 ; MULTIPLY ACCUMULATED SUM BY X
DFAD A3,0(A6) ; ADD NEXT CONSTANT INTO PARTIAL SUM
ADDI A6,2 ; UPDATE POINTER TO NEXT CONSTANT
CAIG A6,LLN17 ; ARE WE DONE YET?
JRST LLN4 ; NO, LOOP BACK FOR MORE TAYLOR SERIES
DFMP A0,A3 ; YES, ONE LAST MULTIPLICATION
DFAD A0,A7 ; AND ADD SERIES SUM INTO FINAL ANSWER
LLN5: POPJ SP,0 ; EXIT
LLN6: EXP 200471174064,325425031470 ; 0.61180 15411 05992 8976
EXP 200402252251,151350376610 ; 0.50455 60107 52395 2859
EXP 177637144373,057714113734 ; 0.40546 51081 08164 3810
EXP 177506061360,207057302360 ; 0.31845 37311 18534 6147
EXP 176710776761,346515041520 ; 0.22314 35513 14209 7553
EXP 176537746034,051711723600 ; 0.17185 02569 26659 2214
EXP 175557032242,271265512760 ; 0.08961 21586 89687 12374
EXP 173770123303,236031377700 ; 0.03077 16586 66753 68689
LLN7: XWD 354000,000000 ; 1.11011 BINARY
XWD 324000,000000 ; 1.10101 BINARY
XWD 300000,000000 ; 1.10000 BINARY
XWD 260000,000000 ; 1.01100 BINARY
XWD 240000,000000 ; 1.01000 BINARY
XWD 230000,000000 ; 1.00110 BINARY
XWD 214000,000000 ; 1.00011 BINARY
XWD 204000,000000 ; 1.00001 BINARY
EDIT(226) ;CHANGE AT LLN8 IN ALGLIB [JBS 4/11/80]
LLN8: EXP 200542710277,276434757153 ;[226] .6931471805599453094172321
LLN9: EXP 175707070707,034343434400 ; 1/9
LLN10: EXP 601400000000,000000000000 ; -1/8
LLN11: EXP 176444444444,222222222222 ; 1/7
LLN12: EXP 601252525252,652525252526 ; -1/6
LLN13: EXP 176631463146,146314631463 ; 1/5
LLN14: EXP 600400000000,000000000000 ; -1/4
LLN15: EXP 177525252525,125252525253 ; 1/3
LLN16: EXP 577400000000,000000000000 ; -1/2
LLN17: XWD 201400,000000 ; 1.0
LLN18: XWD 000000,000000 ;FOR KI10 DOUBLE-LENGTH ZERO
XWD 000000,000000
LIT
PRGEND
TITLE DFAD0 - KA10/KI10 DOUBLE PRECISION ADD (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<17>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(17):
DFAD A0,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFSB0 - KA10/KI10 DOUBLE PRECISION SUBTRACT (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<20>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(20):
DFSB A0,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFMP0 - KA10/KI10 DOUBLE PRECISION MULTIPLY (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<21>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(21):
DFMP A0,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFDV0 - KA10/KI10 DOUBLE PRECISION DIVIDE (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<22>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(22):
DFDV A0,(AX)
POPJ SP,0
LIT
PRGEND
TITLE RDFSB0 - KA10/KI10 DOUBLE PRECISION REVERSE SUBTRACT (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<23>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(23): DMOVN A0,A0 ; NEGATE LEFT HAND OPERAND
DFAD A0,(AX) ; ADD RIGHT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE RDFDV0 - KA10/KI10 DOUBLE PRECISION REVERSE DIVIDE (A0,A1)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A0,A1
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A0,A1
SEARCH ALGPRM,ALGSYS
%ENTER<24>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(24): DMOVEM A0,%SYS12(DB) ; SAVE LEFT HAND OPERAND
DMOVE A0,(AX) ; LOAD RIGHT HAND OPERAND INTO A0,A1
DFDV A0,%SYS12(DB) ; AND DIVIDE BY LEFT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE DFAD3 - KA10/KI10 DOUBLE PRECISION ADD (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<25>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(25):
DFAD A3,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFSB3 - KA10/KI10 DOUBLE PRECISION SUBTRACT (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<26>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(26):
DFSB A3,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFMP3 - KA10/KI10 DOUBLE PRECISION MULTIPLY (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<27>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(27):
DFMP A3,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFDV3 - DOUBLE PRECISION DIVIDE (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<30>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(30):
DFDV A3,(AX)
POPJ SP,0
LIT
PRGEND
TITLE RDFSB3 - KA10/KI10 DOUBLE PRECISION REVERSE SUBTRACT (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<31>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(31):
DMOVN A3,A3 ; NEGATE LEFT HAND OPERAND
DFAD A3,(AX) ; ADD RIGHT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE RDFDV3 - KA10/KI10 DOUBLE PRECISION REVERSE DIVIDE (A3,A4)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A3,A4
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A3,A4
SEARCH ALGPRM,ALGSYS
%ENTER<32>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(32):
DMOVEM A3,%SYS12(DB) ; SAVE LEFT HAND OPERAND
DMOVE A3,(AX) ; LOAD RIGHT HAND OPERAND INTO A3,A4
DFDV A3,%SYS12(DB) ; AND DIVIDE BY LEFT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE DFAD6 - KA10/KI10 DOUBLE PRECISION ADD (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<33>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(33):
DFAD A6,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFSB6 - KA10/KI10 DOUBLE PRECISION SUBTRACT (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<34>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(34):
DFSB A6,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFMP6 - KA10/KI10 DOUBLE PRECISION MULTIPLY (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<35>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(35):
DFMP A6,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFDV6 - KA10/KI10 DOUBLE PRECISION DIVIDE (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<36>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(36):
DFDV A6,(AX)
POPJ SP,0
LIT
PRGEND
TITLE RDFSB6 - KA10/KI10 DOUBLE PRECISION REVERSE SUBTRACT (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<37>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(37): DMOVN A6,A6 ; NEGATE LEFT HAND OPERAND
DFAD A6,(AX) ; ADD RIGHT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE RDFDV6 - KA10/KI10 DOUBLE PRECISION REVERSE DIVIDE (A6,A7)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A6,A7
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A6,A7
SEARCH ALGPRM,ALGSYS
%ENTER<40>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(40):
DMOVEM A6,%SYS12(DB) ; SAVE LEFT HAND OPERAND
DMOVE A6,(AX) ; LOAD RIGHT HAND OPERAND INTO A6,A7
DFDV A6,%SYS12(DB) ; AND DIVIDE BY LEFT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE DFAD9 - KA10/KI10 DOUBLE PRECISION ADD (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<41>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(41):
DFAD A11,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFSB9 - KA10/KI10 DOUBLE PRECISION SUBTRACT (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<42>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(42):
DFSB A11,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFMP9 - KA10/KI10 DOUBLE PRECISION MULTIPLY (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<43>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(43):
DFMP A11,(AX)
POPJ SP,0
LIT
PRGEND
TITLE DFDV9 - KA10/KI10 DOUBLE PRECISION DIVIDE (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<44>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(44):
DFDV A11,(AX)
POPJ SP,0
LIT
PRGEND
TITLE RDFSB9 - KA10/KI10 DOUBLE PRECISION REVERSE SUBTRACT (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<45>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(45): DMOVN A11,A11 ; NEGATE LEFT HAND OPERAND
DFAD A11,(AX) ; ADD RIGHT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE RDFDV9 - KA10/KI10 DOUBLE PRECISION REVERSE DIVIDE (A11,A12)
; ON ENTRY:
; THE LEFT HAND OPERAND IS IN A11,A12
; THE RIGHT HAND OPERAND IS ADDRESSED BY AX
; THE LINK IS ON THE STACK
; ON EXIT, THE RESULT IS IN A11,A12
SEARCH ALGPRM,ALGSYS
%ENTER<46>
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
LABEL(46): DMOVEM A11,%SYS12(DB) ; SAVE LEFT HAND OPERAND
DMOVE A11,(AX) ; LOAD RIGHT HAND OPERAND INTO A11,A12
DFDV A11,%SYS12(DB) ; AND DIVIDE BY LEFT HAND OPERAND
POPJ SP,0
LIT
PRGEND
TITLE DIM - ARRAY DIMENSION ROUTINE
; INTEGER PROCEDURE DIM(A); (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) ARRAY A;
.EXIT=1
.A=3
SEARCH ALGPRM,ALGSYS
LIBENT(300,DIM)
XWD 0,4
XWD $PRO!$I!$SIM,2
XWD $ARR!$WV!$FON,.A
HLRE A0,.A+1(DL)
MOVNM A0,.EXIT+1(DL) ; GET NUMBER OF DIMENSIONS
JRST .EXIT(DL)
LIT
PRGEND
TITLE LB/UB - ARRAY BOUND ROUTINE
; INTEGER PROCEDURE LB(A,N); VALUE N; (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) ARRAY; INTEGER N;
; INTEGER PROCEDURE UB(A,N); VALUE N; (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) ARRAY; INTEGER N;
.EXIT=1
.LU=3
.A=4
.N=6
SEARCH ALGPRM,ALGSYS
LIBENT(301,LB)
XWD 0,6
XWD $PRO!$I!$SIM,3
XWD $ARR!$WV!$FON,.A
XWD $VAR!$I!$FOV,.N
SETZM .LU(DL) ; FLAG AS LB ENTRY
JRST LB1
LIBENT(302,UB)
XWD 0,6
XWD $PRO!$I!$SIM,3
XWD $ARR!$WV!$FON,.A
XWD $VAR!$I!$FOV,.N
MOVEI A0,1
MOVEM A0,.LU(DL) ; FLAG AS UB ENTRY
LB1: MOVE A0,.N(DL) ; GET SUBSCRIPT NUMBER
JUMPLE A0,LBUB1 ; ANY GOOD?
HLRE A1,.A+1(DL)
MOVN A1,A1 ; GET NUMBER OF SUBSCRIPTES
CAMGE A1,A0 ; ENOUGH
JRST LBUB1 ; NO
HRRZ A1,.A+1(DL) ; GET DOPE VECTOR ADDRESS
LSH A0,1 ; DOUBLE SUBSCRIPT NUMBER
ADD A1,A0
ADD A1,.LU(DL) ; AND ALLOW FOR LB/UB
SKIPA A1,-2(A1) ; GET RELEVANT BOUND
LBUB1: MOVEI A1,0 ; OUT OF RANGE
MOVEM A1,.EXIT+1(DL)
JRST .EXIT(DL)
LIT
PRGEND
TITLE IMIN/IMAX - INTEGER MINIMUM/MAXIMUM ROUTINES
; INTEGER PROCEDURE IMIN(I); VALUE I; INTEGER I;
; INTEGER PROCEDURE IMAX(I); VALUE I; INTEGER I;
SEARCH ALGPRM,ALGSYS
DEFINE REP(M,A,I)
<Q=0
R=A-I
REPEAT PRMMAX, <
IF2,
<Q=Q+1
R=R+I>
M \Q,\R>>
DEFINE DECL(A,B)
<IF2, <.I'A=B>>
DEFINE PAR(A,B)
<IF1, <Z>
IF2, <XWD $VAR!$I!$FOV,.I'A>>
.EXIT=1
.MM=3
.V=4
REP DECL,5,1
LIBENT(303,IMIN,.V)
XWD 0,PRMMAX+4
XWD $PRO!$I!$SIM,PRMMAX+1
REP PAR,5,1
MOVEI A2,0 ; IMIN FLAG
JRST IM1
LIBENT(304,IMAX,.V)
XWD 0,PRMMAX+4
XWD $PRO!$I!$SIM,PRMMAX+1
REP PAR,5,1
MOVEI A2,1 ; IMAX FLAG
IM1: MOVN A1,.V(DL) ; NUMBER OF PARAMETERS+1
AOJE A1,IM5 ; NO PARAMETERS?
HRLZ A1,A1
HRRI A1,.I1(DL) ; SET UP COUNTER POINTER
SKIPE A2 ; MIN OR MAX
JRST IM3
HRLOI A0,377777 ; MIN
IM2: CAMLE A0,(A1)
MOVE A0,(A1)
AOBJN A1,IM2
JRST IM6
IM3: HRLZI A0,400000 ; MAX
IM4: CAMGE A0,(A1)
MOVE A0,(A1)
AOBJN A1,IM4
JRST IM6
IM5: MOVEI A0,0 ; NO PARAMETER CASE
IM6: MOVEM A0,.EXIT+1(DL) ; RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE RMIN/RMAX - REAL MINIMUM/MAXIMUM ROUTINES
; REAL PROCEDURE RMIN(X); VALUE X; REAL X;
; REAL PROCEDURE RMAX(X); VALUE X; REAL X;
SEARCH ALGPRM,ALGSYS
DEFINE REP(M,A,I)
<Q=0
R=A-I
REPEAT PRMMAX, <
IF2,
<Q=Q+1
R=R+I>
M \Q,\R>>
DEFINE DECL(A,B)
<IF2, <.X'A=B>>
DEFINE PAR(A,B)
<IF1, <Z>
IF2, <XWD $VAR!$R!$FOV,.X'A>>
.EXIT=1
.MM=3
.V=4
REP DECL,5,1
LIBENT(305,RMIN,.V)
XWD 0,PRMMAX+4
XWD $PRO!$R!$SIM,PRMMAX+1
REP PAR,5,1
MOVEI A2,0 ; RMIN FLAG
JRST RM1
LIBENT(306,RMAX,.V)
XWD 0,PRMMAX+4
XWD $PRO!$R!$SIM,PRMMAX+1
REP PAR,5,1
MOVEI A2,1 ; RMAX FLAG
RM1: MOVN A1,.V(DL) ; NUMBER OF PARAMETERS+1
AOJE A1,RM5 ; NO PARAMETERS?
HRLZ A1,A1
HRRI A1,.X1(DL) ; SET UP COUNTER POINTER
SKIPE A2 ; MIN OR MAX
JRST RM3
HRLOI A0,377777 ; MIN
RM2: CAMLE A0,(A1)
MOVE A0,(A1)
AOBJN A1,RM2
JRST RM6
RM3: MOVE A0,[
XWD 400000,000001]
RM4: CAMGE A0,(A1)
MOVE A0,(A1)
AOBJN A1,RM4
JRST RM6
RM5: MOVEI A0,0 ; NO PARAMETER CASE
RM6: MOVEM A0,.EXIT+1(DL) ; RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE LMIN/LMAX - LONG REAL MINIMUM/MAXIMUM ROUTINES
; LONG REAL PROCEDURE LMIN(D); VALUE D; LONG REAL D;
; LONG REAL PROCEDURE LMAX(D); VALUE D; LONG REAL D;
SEARCH ALGPRM,ALGSYS
DEFINE REP(M,A,I)
<Q=0
R=A-I
REPEAT PRMMAX, <
IF2,
<Q=Q+1
R=R+I>
M \Q,\R>>
DEFINE DECL(A,B)
<IF2, <.D'A=B>>
DEFINE PAR(A,B)
<IF1, <Z>
IF2, <XWD $VAR!$LR!$FOV,.D'A>>
.EXIT=1
.MM=4
.V=5
REP DECL,6,2
LIBENT(307,LMIN,.V)
XWD 0,2*PRMMAX+5
XWD $PRO!$LR!$SIM,PRMMAX+1
REP PAR,6,2
MOVEI A0,0 ; FLAG AS LMIN
JRST LM1
LIBENT(310,LMAX,.V)
XWD 0,2*PRMMAX+5
XWD $PRO!$LR!$SIM,PRMMAX+1
REP PAR,6,2
MOVEI A0,1 ; FLAG AS LMAX
LM1: MOVN A2,.V(DL) ; NUMBER OF PARAMETERS+1
AOJE A2,LM7 ; NO PARAMETERS?
HRLZ A2,A2
HRRI A2,.D1(DL) ; SET UP COUNTER POINTER
SKIPE A0 ; MIN OR MAX?
JRST LM4
HRLOI A0,377777 ; MIN
HRLOI A1,344777
LM2: CAMN A0,(A2)
CAMLE A1,1(A2)
CAMGE A0,(A2)
AOJA A2,LM3
DMOVE A0,(A2)
ADDI A2,1
LM3: AOBJN A2,LM2
JRST LM8
LM4: HRLZI A0,400000 ; MAX
MOVE A1,[
XWD 344000,000001]
LM5: CAMN A0,(A2)
CAMGE A1,1(A2)
CAMLE A0,(A2)
AOJA A2,LM6
DMOVE A0,(A2)
ADDI A2,1
LM6: AOBJN A2,LM5
JRST LM8
LM7: SETZB A0,A1 ; NO PARAMETER CASE
LM8: DMOVEM A0,.EXIT+1(DL) ; RESULT
JRST .EXIT(DL)
LIT
PRGEND
TITLE GFIELD/SFIELD - FIELD ACCESS ROUTINES
; INTEGER PROCEDURE GFIELD(A,I,J); VALUE A,I,J;
; (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) A; INTEGER I,J;
; PROCEDURE SFIELD(A,I,J,N); VALUE I,J,N;
; (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) A; INTEGER I,J,N;
.EXIT=1
.A=3
.I=6
.J=7
.N=10
SEARCH ALGPRM,ALGSYS
LIBENT(312,SFIELD)
XWD 0,10
XWD $PRO!$N!$SIM,5
XWD $VAR!$WV!$FON,.A
XWD $VAR!$I!$FOV,.I
XWD $VAR!$I!$FOV,.J
XWD $VAR!$I!$FOV,.N
MOVEI A1,1 ; SET SFIELD FLAG
JRST GSF1
LIBENT(311,GFIELD)
XWD 0,10
XWD $PRO!$I!$SIM,4
XWD $VAR!$WV!$FOV,.A
XWD $VAR!$I!$FOV,.I
XWD $VAR!$I!$FOV,.J
MOVEI A1,0 ; CLEAR SFIELD FLAG
GSF1: MOVE A2,PRGLNK(DL) ; GET PROGRAM LINK
SUBI A2,3(A1) ; GET ADDRESS OF AP FOR A
HLRZ A0,(A2)
ANDI A0,$TYPE ; GET TYPE OF A
CAIE A0,$LR
CAIN A0,$S
HRLI A1,400000 ; SET LONG FLAG IF DOUBLE WORD
SKIPL A2,.I(DL) ; GET I
SKIPG A3,.J(DL) ; AND J
GSF2: SYSER1 15,0 ; BAD VALUES
TLZE A1,400000
JRST GSF5 ; LONG CASE?
MOVEI A4,^D36 ; NO
SUB A4,A2
SUB A4,A3 ; FORM 36-I-J
JUMPL A4,GSF2 ; FAIL UNLESS I+J <= 36
GSF3: LSH A4,6
ADDI A4,(A3) ; FORM 64*P + S
ROT A4,-14 ; FUDGE BYTE POINTER
JUMPN A1,GSF4 ; JUMP IF SFIELD
EDIT (244) ; [244] FIX GFIELD FOR STRINGS
CAIE A0,$S ; [244] ELSE GFIELD - IS THIS A STRING?
JRST GSF98 ; [244] NO, LONG REAL - JUMP AHEAD
EDIT (245) ; [245] FIX GFIELD/SFIELD FOR STRINGS
; [245] INSTALL EDIT 244 BEFORE THIS ONE
SKIPN A1,.A(DL) ; [245] LOAD STRING ADDR. AND SKIP IF SET UP
JRST GSF2 ; [245] ERROR IF STRING NOT SET UP YET
ADDI A4,@A1 ; [244] [245] CALCULATE FINAL BYTE ADDR.
SKIPA ; [244] SKIP AHEAD
GSF98: ADDI A4,.A(DL) ; [244] ADD ADDRESS OF ARG. TO BYTE POINTER
LDB A0,A4 ; LOAD THE BYTE
MOVEM A0,.EXIT+1(DL) ; PUT RESULT INTO MEMORY
JRST .EXIT(DL)
;
; SFIELD - SET A BYTE INTO A VARIABLE
;
GSF4: MOVE A5,A0 ; [245] SAVE VARIABLE TYPE IN A5
XCT .A(DL) ; [245] LOAD "A" (OR STRING HEADER)
CAIE A5,$S ; [245] IS THIS A STRING?
JRST GSF93 ; [245] NO, JUMP AHEAD
JUMPE A0,GSF2 ; [245] YES, BUT ERROR IF STRING DOESN'T EXIST
HRR A4,A0 ; [245] ELSE PUT ADDRESS OF STRING IN BYTE PTR.
MOVE A5,.N(DL) ; [245] LOAD BYTE TO BE DEPOSITED
DPB A5,A4 ; [245] PUT IT IN THE STRING
JRST .EXIT(DL) ; [245] EXIT
GSF93: MOVE A5,.N(DL) ; [245] LOAD BYTE TO BE DEPOSITED
DPB A5,A4 ; [245] DEPOSIT THE BYTE
MOVEM A0,(SP) ;
XCT .A+1(DL) ; AND WRITE IT IN A
JRST .EXIT(DL) ;
;
; GFIELD/SFIELD - FOR 2 WORD ARGUMENT (LONG REAL OR STRING).
;
GSF5: MOVEI A5,^D72 ; LONG CASE
SUB A5,A2
SUB A5,A3 ; FORM 72-I-J
JUMPL A5,GSF2 ; FAIL UNLESS I+J <= 72
HRREI A4,-^D36(A5) ; TEST FOR SIMPLE CASE
JUMPGE A4,GSF3 ; OF I+J <= 36
CAIGE A2,^D36 ; I >= 36?
JRST GSF6 ; NO, BYTE IS SPLIT ACROSS TWO WORDS
MOVEI A4,100(A5) ; YES - FUDGE BYTE POINTER FOR A1
JRST GSF3 ; GO HANDLE IT LIKE A 1-WORD GFIELD
;
; GFIELD/SFIELD FOR TWO WORD VARIABLE, BYTE SPLIT ACROSS WORD BOUNDRIES.
;
GSF6: CAILE A3,^D36 ; FRAGMENTED CASE
JRST GSF2 ; LOSES IF J > 36
MOVN A4,A4 ; S2 = I+J-36
MOVEI A2,(A4) ; SAVE SHIFT
SUBI A3,(A4) ; S1 = 36-I
ROT A3,-14 ; FORM FIRST BYTE POINTER
LSH A5,6
ADDI A4,(A5)
ROT A4,-14
ADDI A4,A1 ; FORM SECOND BYTE POINTER
JUMPN A1,GSF7 ; JUMP IF THIS IS AN SFIELD
CAIE A0,$S ; [244] ELSE GFIELD - IS THIS A STRING?
JRST GSF99 ; [244] NO, LONG REAL - JUMP AHEAD
SKIPN A1,.A(DL) ; [245] LOAD STRING ADDR. AND SKIP IF SET UP
JRST GSF2 ; [244] [245] NOT SET UP YET - ERROR
DMOVE A0,@A1 ; [244] [245] OK - LOAD FIRST TWO STRING WORDS
JRST GSF91 ; [244] [245]
GSF99: DMOVE A0,.A(DL) ; [244] LOAD BOTH WORDS OF VARIABLE
GSF91: LDB A0,A3 ; [245] GET FIRST BYTE
LDB A1,A4 ; GET SECOND BYTE
LSH A0,(A2)
ADD A0,A1 ; ASSEMBLE RESULT
MOVEM A0,.EXIT+1(DL)
JRST .EXIT(DL)
;
; SFIELD FOR TWO WORD VARIABLE, BYTE SPLIT ACROSS WORD BOUNDIRES.
;
GSF7: PUSH SP,A2
PUSH SP,A3
MOVE A5,A0 ; [245] SAVE VARIABLE TYPE IN A5
XCT .A(DL) ; GET VALUE OF A
MOVE A3,(SP) ; RESTORE BYTE POINTERS
MOVN A2,-1(SP) ; AND SHIFT
CAIE A5,$S ; [245] IS THIS A STRING?
JRST GSF92 ; [245] NO, LONG REAL - JUMP AHEAD
JUMPE A0,GSF2 ; [245] YES, ERROR IF STRING DOESN'T EXIST YET
HRR A3,A0 ; [245] LOAD STRING ADDRESS FOR FIRST WORD
HRR A4,A0 ; [245] DO IT FOR A4 TOO
AOS A4 ; [245] INCREMENT TO SECOND WORD OF STRING
MOVE A5,.N(DL) ; [245] LOAD BYTE TO BE WRITTEN
DPB A5,A4 ; [245] STORE PART OF BYTE IN SECOND WORD
LSH A5,(A2) ; [245] ROTATE REMAINDER OF BYTE INTO POSITION
DPB A5,A3 ; [245] STORE REMAINDER OF BYTE IN FIRST WORD
POP SP,(SP) ; [245] FIX STACK POINTER
POP SP,(SP) ; [245]
JRST .EXIT(DL) ; [245] ALL DONE
GSF92: MOVE A5,.N(DL) ; [245] GET BYTE VALUE FROM N
DPB A5,A4 ; DEPOSIT SECOND BYTE
LSH A5,(A2) ; SHIFT DOWN BYTE
DPB A5,A3 ; DEPOSIT FIRST BYTE
DMOVEM A0,-1(SP) ; SAVE NEW VALUE
POP SP,A1
POP SP,A0 ; RESTORE NEW VALUE
XCT .A+1(DL) ; AND STORE IT
JRST .EXIT(DL)
LIT
PRGEND
TITLE COPY - COPY STRING ROUTINE
; STRING PROCEDURE COPY(S,M,N); VALUE M,N; STRING S; INTEGER M,N;
.EXIT=1
.S=4
.M=7
.N=10
.V=11
SEARCH ALGPRM,ALGSYS
LIBENT(314,COPY,.V)
XWD 0,11
XWD $PRO!$S!$SIM,4
XWD $VAR!$S!$FON,.S
XWD $VAR!$I!$FOV,.M
XWD $VAR!$I!$FOV,.N
SOSN .V(DL) ; ANY PARAMETERS?
SYSER1 10,0 ; NO - COMPLAIN
XCT .S(DL) ; GET ADDRESS OF STRING
EDIT(023); SAVE STRING HEADER ADDRESS DELOCATED
MOVEM A2,%SYS11(DB) ; [E023]
MOVEI A2,@A2
LDB A0,[POINT 24,STR2(A2),35] ; AND ITS LENGTH
MOVEI A7,1
MOVE A10,A0 ; SET UP DEFAULT PARAMETERS
SOSN A1,.V(DL)
JRST COPY1 ; ONLY ONE PARAMETER
CAMLE A10,.M(DL)
MOVE A10,.M(DL) ; MIN(M,LENGTH(S))
SOJE A1,COPY1 ; IF TWO PARAMETERS
MOVE A7,A10
CAIGE A7,1
MOVEI A7,1 ; MAX(M,1)
MOVE A10,.N(DL)
CAMLE A10,A0
MOVE A10,A0 ; MIN(N,LENGTH(S))
COPY1: SUB A10,A7
AOJG A10,.+3 ; NUMBER OF BYTES TO BE COPIED
MOVEI A10,0
JRST COPY2 ; MAYBE NONE AT ALL
LDB A0,[POINT 6,STR1(A2),11] ; GET BYTE SIZE
MOVEI A1,^D36
IDIV A1,A0 ; CALCULATE NUMBER OF BYTES PER WORD
MOVE A0,A10
IDIVI A0,(A1)
JUMPE A1,.+2
ADDI A0,1 ; NUMBER OF WORDS IN BYTE STRING
DMOVEM A7,%SYS12(DB) ; SAVE A7,A10
PUSHJ SP,GETCLR ; ASK FOR SPACE FOR STRING (ZEROED)
DMOVE A7,%SYS12(DB) ; RESTORE A7,A10
COPY2: MOVEI A2,.EXIT+1(DL) ; ADDRESS OF NEW STRING
MOVEI A4,(A1) ; ADDRESS OF NEW BYTE STRING
MOVEI A3,@%SYS11(DB) ; [E023] ADDRESS OF OLD HEADER
DMOVE A0,(A3) ; LOAD UP VALUE OF OLD STRING
JSP AX,CPYSTR ; AND COPY STRING
JRST .EXIT(DL)
LIT
PRGEND
TITLE TRAP - TRAP ERROR ROUTINE
; PROCEDURE TRAP (N, L); VALUE N, L; INTEGER N; LABEL L;
.EXIT=1
.N=2
.L=3
.V=6
SEARCH ALGPRM,ALGSYS
LIBENT(315,TRAP,.V)
XWD 0,6
XWD $PRO!$N!$SIM,3
XWD $VAR!$I!$FOV,.N
XWD $VAR!$L!$FOV,.L
SOSN .V(DL) ; HOW MANY ACTUAL PARAMETERS?
SYSER1 10,0 ; NONE - COMPLAIN
SKIPL A2,.N(DL) ; GET TRAP NUMBER
CAIL A2,100
JRST .EXIT(DL) ; OUT OF RANGE
MOVEI A0,0
ADDI A2,(DB)
HRRZ A1,%TRAPS(A2)
JUMPE A1,TRAP0
PUSHJ SP,GETOWN ; YES - RELEASE IT
TRAP0: MOVEI A1,0
SOSN .V(DL)
JRST TRAP1 ; TRAP TO BE UNSET
XCT .L(DL) ; GET LABEL ADDRESS
JUMPE A2,TRAP0 ; EXIT IF SWITCH OUT OF RANGE
HLRZ A3,A2 ; GET F[0]
ADDI A3,(DB)
HLRZ A4,2(A3) ; SAVE ITS DL
HRRZ A3,1(A3) ; AND GET THE ACTUAL LABEL ADDRESS
HRRZ A0,1(A3) ; PROCEDURE LEVEL OF LABEL
ADDI A0,2
PUSH SP,A3 ; SAVE LABEL ADDRESS
PUSH SP,A4 ; AND RELEVANT DL
PUSHJ SP,GETOWN ; GET DUMP AREA
POP SP,A2 ; RESTORE RELEVANT DL
POP SP,(A1) ; STORE LABEL ADDRESS
HLRZ A0,-1(A1) ; LABEL
SUBI A0,2 ; PROCEDURE LEVEL + 1
HRLM A0,(A1) ;
ADDI A2,(DB) ; RELOCATE RELEVANT DL
HRLZI A2,(A2) ;
HRRI A2,1(A1) ; SET UP BLT POINTER
ADDI A0,(A1) ;
BLT A2,@A0 ; AND MAKE COPY OF DISPLAY
TRAP1: MOVE A3,.N(DL)
ADDI A3,(DB)
MOVEM A1,%TRAPS(A3) ; SET UP TRAP ENTRY
JRST .EXIT(DL)
LIT
PRGEND
TITLE FCALLS - FORTRAN INTERFACE ROUTINES
SEARCH ALGPRM,ALGSYS
%ENTER<434,435,436,437,440>
%ENTER<450,451,452,453,454>
EXTERNAL %ALGDR
SALL
%SUBTTL(ALGLIB,ALGOL LIBRARY)
.EXIT=1
.SUBR=4
LABEL(450): ; F10CALL
LABEL(451): ; F10ICALL
LABEL(452): ; F10RCALL
LABEL(453): ; F10DCALL
LABEL(454): ; F10LCALL
TDZA A0,A0 ; F10 - SET A0 TO 0
LABEL(434): ; CALL
LABEL(435): ; ICALL
LABEL(436): ; RCALL
LABEL(437): ; DCALL
LABEL(440): ; LCALL
MOVEI A0,1 ; F40 - SET A0 TO 1
SKIPE A13,A0 ; SKIP IF F10 & CLEAR A13
MOVSI A13,(JUMP) ; F40 - SET NOOP CODE
HRRZS A2,(SP) ; GET RETURN LINK
HRRZ A1,(A2) ; GET NUMBER OF PARAMETERS (+1)
HRLI A2,-1(A1) ; GET ACTUAL NUMBER OF PARAMETERS
TLC A2,-1 ; GET -(N+1) IN L.H. OF A2
AOBJN A2,.+2 ; ARE THERE ANY PARAMETERS ?
SYSER1 10,0 ; NO - FATAL ERROR
MOVEI A3,(SP) ; SAVE STACK POINTER
PUSH SP,A0 ; STACK F10/F40 INDICATOR
PUSH SP,A0 ; RESERVE WORD FOR ARRAY COUNT
PUSH SP,[JSP AX,PARAM]; STACK CALL TO PARAM
SKIPN A0 ; WHAT TYPE OF FORTRAN ?
TROA A0,F10PMB ; F10 - A0 := F10 PMB ADDRESS
MOVEI A0,F40PMB ; F40 - A0 := F40 PMB ADDRESS
PUSH SP,A0 ; STACK PMB ADDRESS
PUSH SP,[EXP 3] ; STACK INITIAL PL,,L
IMULM A1,(SP) ; (3 WORDS/PARAMETER + 3)
PUSH SP,A1 ; STACK FTYPE,,M+1
MOVE A1,(A2) ; GET DESCRIPTOR FOR FIRST ARGUMENT
TLC A1,<$PRO!$EXT> ; PREPARE FOR TESTS
TLCN A1,$PRO ; IS IT A PROCEDURE ?
TLNE A1,$STAT ; YES - IS IT EXTERNAL ?
CALL01: SYSER1 7,0 ; NO TO EITHER - FATAL ERROR
HLLM A1,(SP) ; SET TYPE BITS OF RESULT FOR PARAM
HRRI A1,.SUBR ; GET OFFSET WITHIN FIXED STACK
SETZ A4, ; CLEAR COUNT OF ARRAYS FOUND
JRST CALL03 ; AND GO SET TYPE FIELD
CALL02: HRRZI A1,3(A1) ; GET NEXT OFFSET WITHIN FIXED STACK
HLL A1,(A2) ; GET KIND,TYPE,STATUS OF NEXT ACTUAL
TLNN A1,$ARR ; VARIABLE OR EXPRESSION ?
JRST CALL04 ; YES
TLNN A1,$EXP ; NO - ARRAY ?
AOJA A4,CALL04 ; YES (COUNT IT IN A4)
TLC A1,$EXT ; NO - MUST BE A PROCEDURE !
TLNE A1,$STAT ; WAS IT EXTERNAL ?
SYSER1 7,0 ; NO - FATAL ERROR
CALL03: TLZA A1,$TYPE ; [PRO] CLEAR TYPE FIELD
CALL04: TLZA A1,<$EXP!$TYPE!$STAT>; [VAR] SET KIND TO $VAR OR $ARR
TLOA A1,$ABN ; [PRO] SET TYPE TO WILD ARITH/BOOL/NON
TLO A1,<$AB!$FON> ; [VAR] SET WILD ARITHMETIC/BOOLEAN BY NAME
PUSH SP,A1 ; STACK FORMAL PARAMETER DESCRIPTOR
AOBJN A2,CALL02 ; REPEAT IF MORE PARAMETERS
PUSH SP,[JRST CALL05]; STACK RETURN JUMP
PUSH SP,A13 ; SAVE OPCODE FOR DESCRIPTORS
PUSH SP,A3 ; SAVE POINTER TO START
PUSH SP,(A3) ; STACK PROGRAM LINK
MOVEM A4,2(A3) ; SAVE COUNT OF ARRAYS
JRST 3(A3) ; **** ENTER PARAM INTERLUDE ****
CALL05: MOVE A3,LINKDL-1(DL) ; PICK UP TOP-OF-STACK ON ENTRY TO FCALL
HRRZ A1,BLKPTR(DL) ; GET CURRENT TOP-OF-STACK (DELOCATED)
HRLI A1,DB ; SET DB INTO INDEX FIELD
EXCH A1,2(A3) ; SWAP WITH COUNT OF ARRAYS
JUMPE A1,.+3 ; ARE THERE ANY ARRAYS ?
PUSH SP,A1 ; IF SO, RESERVE ONE WORD ON
SOJG A1,.-1 ; THE STACK FOR EACH ONE
MOVEI A2,CALL20 ; GET INTERMEDIATE RETURN ADDRESS
EXCH A2,PRGLNK(DL) ; SWAP WITH (POSSIBLY DELOCATED) LINK
EXCH A2,(A3) ; SWAP THIS WITH ORIGINAL LINK
SUBI A2,@(A3) ; GET DIFFERENCE (-(N+1))
AOS A1,A2 ; ADD 1 (STEP OVER COUNT OF PARAMETERS)
ADD A2,(A3) ; AND GET (DELOCATED?) ADDR OF DESCRIPTORS
HRRZ A0,.SUBR+1(DL) ; GET ADDRESS OF FORTRAN ROUTINE
ADDM A0,1(A3) ; SAVE IT (+1 IF F40 CALL)
SUBI A3,-2(DB) ; DELOCATE ADDRESS
HRLI A3,DB ; SET DB INTO INDEX FIELD
MOVEM A3,LINKDL-1(DL) ; AND SAVE IT
HRLZI A3,1(A1) ; SET A3 TO ARG-COUNT WORD FOR F10
PUSH SP,A3 ; PUSH IT ONTO PARAMETER BLOCK
MOVE A3,[Z .SUBR(DL)]; GET DELOCATED POINTER INTO A3
AOJGE A1,CALL07 ; JUMP IF NO PARAMETERS TO FORTRAN
CALL06: HRRI A2,1(A2) ; STEP TO NEXT DESCRIPTOR WORD
HRRI A3,3(A3) ; AND NEXT 3-WORD AREA ON LOCAL STACK
MOVE A4,@A2 ; GET DESCRIPTOR WORD
TLNN A4,$ARR ; DECODE TYPE
SKIPA A13,[ARGVAR,,ARGEXP]; TYPE 0 (VAR) OR TYPE 1 (EXP)
MOVE A13,[ARGARR,,ARGPRO]; TYPE 2 (ARR) OR TYPE 3 (PRO)
TLNN A4,$EXP ; DECIDE WHICH HALF WE NEED
MOVS A13,A13 ; LEFT HALF - SWAP HALVES
PUSHJ SP,(A13) ; EVALUATE ADDRESS INTO A13
TLNN A4,<$TYPE-$B> ; IS TYPE BOOLEAN ?
TLO A13,(Z 01,0) ; YES - FORTRAN TYPE CODE = 1
TLNN A4,<$TYPE-$I> ; IS TYPE INTEGER ?
TLO A13,(Z 02,0) ; YES - FORTRAN TYPE CODE = 2
TLNN A4,<$TYPE-$R> ; IS TYPE REAL ?
TLO A13,(Z 04,0) ; YES - FORTRAN TYPE CODE = 4
TLNN A4,<$TYPE-$LR> ; IS TYPE LONG REAL ?
TLO A13,(Z 10,0) ; YES - FORTRAN TYPE CODE = 8
IOR A13,LINKDL-2(DL); SET NOOP IF F40
PUSH SP,A13 ; PUSH PARAMETER WORD ONTO STACK
AOJL A1,CALL06 ; REPEAT FOR EACH PARAMETER
CALL07: PUSH SP,[POPJ SP,] ; PUSH RETURN INSTRUCTION (FOR F40)
PUSH SP,DB ; SAVE ENVIRONMENT
PUSH SP,DL ; ..
MOVEI A1,@LINKDL-1(DL); GET ADDRESS OF ARRAY-WORD POINTER
AOS A2,(A1) ; GET DELOCATED ADDRESS OF COUNT WORD
MOVEI A2,@A2 ; CONVERT TO ABSOLUTE ADDRESS
AOS AX,A2 ; POINT AX TO FORTRAN ARG BLOCK
HLL A2,-1(A2) ; GET AOBJN WORD OVER ARG BLOCK
JUMPGE A2,CALL09 ; JUMP IF NO PARAMETERS TO FORTRAN
CALL08: MOVE A3,(A2) ; GET A FORTRAN DESCRIPTOR WORD
HRRI A3,@A3 ; CONVERT TO ABSOLUTE ADDRESS
TLZE A3,17 ; MAKE SURE INDEX FIELD IS ZERO
MOVEM A3,(A2) ; UPDATE ADDRESS IF DYNAMIC
AOBJN A2,CALL08 ; REPEAT FOR EACH PARAMETER
CALL09: MOVEI A2,(SP) ; GET ADDRESS OF TOP-OF-STACK
PUSH SP,A2 ; AND REMEMBER IT
PUSHJ SP,@-1(A1) ; **** CALL FORTRAN ROUTINE ****
POP SP,A2 ; RETURN HERE FROM FORTRAN ROUTINE
CAIE A2,(SP) ; HAS STACK BEEN SHIFTED ?
LIBERR 6,0 ; YES - VERY FATAL
POP SP,DL ; RESTORE ENVIRONMENT
POP SP,DB ; ..
MOVEM A0,.EXIT+1(DL) ; STORE ANSWER (IF ANY)
MOVEM A1,.EXIT+2(DL) ; (2 WORDS IF LONG REAL)
CALL10: SOS A2,@LINKDL-1(DL); STEP ARRAY WORD POINTER BACK ONE
SKIPGE A1,@A2 ; PICK UP A WORD
JRST CALL15 ; NEGATIVE MEANS BLOCK POINTER
HRRZ A3,(A1) ; GET ALGOL BASE ADDRESS
SOJ A3,.+1 ; (MINUS 1, FOR "PUSH")
HLRZ A4,(A1) ; AND FORTRAN BASE ADDRESS
MOVE A0,-2(A4) ; GET WORDS PER ELEMENT
CALL11: MOVEI A5,2(A1) ; GET ADDRESS OF TABLE
PUSH A3,(A4) ; COPY ONE WORD BACK TO ALGOL ARRAY
CAIN A0,2 ; TWO WORDS PER ELEMENT ?
PUSH A3,1(A4) ; YES - COPY OVER SECOND WORD
CALL12: ADD A4,2(A5) ; STEP TO NEXT FORTRAN ADDRESS
SOSLE 1(A5) ; ALL DONE FOR THIS SUBSCRIPT ?
JRST CALL11 ; NO - COPY NEXT ELEMENT
MOVE A6,0(A5) ; YES - RESET SUBSCRIPT RANGE
MOVEM A6,1(A5) ; TO (UB-LB)+1
SUB A4,-1(A5) ; STEP BACK OVER SUB-ARRAY
MOVEI A5,3(A5) ; STEP TO NEXT SUBSCRIPT
SKIPE (A5) ; ALL DONE ?
JRST CALL12 ; IF NOT, CONTINUE COPYING
SETZM A0 ; FLAG GIVING BACK SPACE
PUSHJ SP,GETOWN ; RETURN IT
JRST CALL10 ; REPEAT FOR NEXT ARRAY
CALL15: MOVEI A2,@A2 ; GET DESIRED TOP-OF-STACK
SUBI A2,(SP) ; GET CORRECTION TO SP
HRLI A2,(A2) ; GET CORRECTION IN LH ALSO
ADD SP,A2 ; ADJUST STACK POINTER
JRST .EXIT(DL) ; **** UNWIND BLOCK STRUCTURE ****
CALL20: MOVEI A2,@(SP) ; GET ADDRESS OF RETURN ADDRESS (+2)
SUBI A2,2(SP) ; STEP STACK POINTER BACK OVER THE
HRLI A2,(A2) ; CALL TO PARAM THAT WAS BUILT UP
ADD SP,A2 ; ON THE STACK
POPJ SP, ; AND RETURN TO CALLING PROGRAM
ARGVAR: JUMPGE A4,STATIC ; DYNAMIC VARIABLE ?
PUSH SP,A1 ; YES - SAVE CURRENT VALUES
PUSH SP,A2 ; OF A1,A2 AND A3
PUSH SP,A3 ; ..
XCT 1,@A3 ; TRY AND GET ADDRESS OF VARIABLE
HRRZ A13,A2 ; SUCCESS - GET 23-BIT ADDRESS
CAIG A13,(SP) ; IN A13 (DELOCATED IF DYNAMIC,
CAIG A13,(DB) ; IN WHICH CASE WE NEED TO SET
JRST .+3 ; DB IN THE INDEX FIELD, AND
SUBI A13,(DB) ; SET THE RIGHT HALF OF A13
HRLI A13,DB ; TO THE OFFSET FOR THIS VARIABLE)
JRST ARGRET ; RESTORE A1,A2,A3,A4 & RETURN
STATIC: HLRZ A13,A4 ; GET DESCRIPTOR
ANDI A13,$STATUS ; MASK TO STATUS FIELD
CAIN A13,$FON ; AND IF FORMAL-BY-NAME
JRST ARGEXP ; TREAT AS A LOCAL (BY VALUE)
MOVEI A13,@A3 ; GET ACTUAL ADDRESS OF 3-WORD BLOCK
MOVE A13,(A13) ; GET F[0] (MOVE/DMOVE INSRUCTION)
TLZ A13,777760 ; CLEAR OPCODE & AC FIELDS
POPJ SP, ; AND RETURN
ARGEXP: PUSH SP,A1 ; ACTUAL ARGUMENT IS AN EXPRESSION
PUSH SP,A2 ; FIRST SAVE A1,A2 AND A3, AS EXPRESSION
PUSH SP,A3 ; COULD INVOLVE A PROCEDURE CALL
XCT @A3 ; EVALUATE EXPRESSION INTO A0,A1
MOVEI A3,@(SP) ; GET ADDRESS OF 3 WORD AREA ON LOCAL
MOVEM A0,0(A3) ; FIXED STACK, AND USE THIS TO STORE
MOVEM A1,1(A3) ; THE VALUE OF THE EXPRESSION
MOVE A13,(SP) ; GET ADDRESS OF PARAMETER
JRST ARGRET ; RESTORE A1,A2,A3,A4 & RETURN
ARGARR: PUSH SP,A1 ; SAVE CURRENT VALUES OF
PUSH SP,A2 ; A1,A2,A3 (DELOCATED, AS
PUSH SP,A3 ; GETOWN MAY SHIFT STACK)
MOVEI A1,@A3 ; GET STATIC ADDRESS OF DESCRIPTOR
HRLI A1,A3 ; AND SET A3 INTO INDEX FIELD
MOVE A2,1(A1) ; GET POINTER TO BOUND PAIRS
HLRE A0,A2 ; GET -(NO OF SUBSCRIPTS) IN A0
MOVEI A5,1 ; ASSUME ONE WORD PER ELEMENT
TLNE A4,$VAR1 ; LONG REAL ARRAY ?
MOVEI A5,2 ; YES - TWO WORDS PER ELEMENT
ARRAY1: HRR A1,(A1) ; GET ADDRESS OF 0'TH ELEMENT
MOVE A3,(A2) ; GET LOWER SUBSCRIPT BOUND
HRRI A1,@A1 ; "ADD" OFFSET TO A1
SUB A3,1(A2) ; -(UB-LB)
MOVN A3,A3 ; +(UB-LB)
AOJ A3,.+1 ; (UB-LB)+1
PUSH SP,A3 ; SAVE RANGE OF SUBSCRIPT
IMUL A5,A3 ; AND ADJUST SIZE
AOBJP A2,ARRAY2 ; LAST SUBSCRIPT ?
AOJA A2,ARRAY1 ; NO - REPEAT FOR NEXT
EDIT(064); Correct base address for long real arrays
ARRAY2: TLNE A4,$VAR1 ; [E064] LONG REAL ARRAY ?
ADD A1,-1(A2) ; [E064] YES - DOUBLE FINAL SUBSCRIPT
PUSH SP,A0 ; SAVE NUMBER OF SUBSCRIPTS
PUSH SP,A1 ; ADDRESS OF FIRST (ALGOL) ELEMENT
PUSH SP,A5 ; SIZE OF ARRAY
MOVN A0,A0 ; OVERHEAD = 3 WORDS PER DIMENSION
IMULI A0,3 ; PLUS THREE HOUSEKEEPING
ADDI A0,3(A5) ; GET SIZE OF OWN AREA NEEDED
PUSHJ SP,GETOWN ; AND ASK FOR IT FROM OTS
POP SP,A2 ; GET SIZE OF ARRAY AGAIN
POP SP,A0 ; AND ADDRESS OF FIRST ALGOL ELEMENT
HRRZM A0,(A1) ; SAVE IN LOCAL AREA
MOVEM A2,1(A1) ; SAVE TOTAL ARRAY SIZE
POP SP,A0 ; GET NUMBER OF DIMENSIONS
MOVEI A13,3(A1) ; INITIALIZE POINTER
ARRAY3: POP SP,A3 ; GET RANGE OF SUBSCRIPT
MOVEM A3,-1(A13) ; SAVE SUBSCRIPT RANGE
MOVEM A3,00(A13) ; AND CURRENT VALUE
IDIVI A2,(A3) ; GET SUB-ARRAY SIZE
MOVEM A2,+1(A13) ; AND SAVE THAT AS WELL
MOVEI A13,3(A13) ; INCREASE POINTER BY THREE
AOJL A0,ARRAY3 ; REPEAT FOR EACH SUBSCRIPT
SETZM -1(A13) ; SET FLAG WORD AT END
HRLM A13,(A1) ; ADDRESS OF FIRST (FORTRAN) ELEMENT
AOS A3,@LINKDL-1(DL); STEP POINTER TO ARRAY WORDS
MOVEM A1,@A3 ; SAVE ADDRESS OF OWN AREA
HRRZ A3,(A1) ; GET ALGOL BASE ADDRESS
HLRZ A4,(A1) ; AND FORTRAN BASE ADDRESS
MOVE A0,-2(A4) ; GET WORDS/ELEMENT
SOJ A0,.+1 ; A0 NOW NON-ZERO FOR TYPE LONG REAL
ARRAY4: MOVEI A5,2(A1) ; GET ADDRESS OF TABLE
MOVE A6,(A3) ; COPY ONE WORD OF THE ALGOL
MOVEM A6,(A4) ; ARRAY TO THE FORTRAN ARRAY
AOJ A3,.+1 ; STEP ALGOL ARRAY ADDRESS
JUMPE A0,ARRAY5 ; TWO WORDS PER ELEMENT ?
MOVE A6,(A3) ; YES - COPY OVER LOW ORDER
MOVEM A6,1(A4) ; WORD OF LONG REAL ITEM
AOJ A3,.+1 ; STEP ALGOL ADDRESS AGAIN
ARRAY5: ADD A4,2(A5) ; STEP TO NEXT FORTRAN ADDRESS
SOSLE 1(A5) ; FINISHED WITH THIS SUBSCRIPT ?
JRST ARRAY4 ; NO - COPY ANOTHER ELEMENT
MOVE A6,(A5) ; YES - GET SUBSCRIPT RANGE
MOVEM A6,1(A5) ; RESET SUBSCRIPT VALUE
SUB A4,-1(A5) ; STEP BACK OVER ENTIRE SUB-ARRAY
MOVEI A5,3(A5) ; STEP TO NEXT SUBSCRIPT
SKIPE (A5) ; LAST ONE ?
JRST ARRAY5 ; IF NOT, CARRY ON COPYING
ARGRET: POP SP,A3 ; RESTORE ORIGINAL VALUES
POP SP,A2 ; OF A1,A2 AND A3
POP SP,A1 ; ..
MOVE A4,@A2 ; GET DESCRIPTOR WORD AGAIN
POPJ SP,
ARGPRO: MOVEI A13,(A4) ; GET PROCEDURE ADDRESS INTO A13
POPJ SP, ; AND RETURN
FORER.::LIBERR 7,0 ; ALLOW FORTRAN TO HAVE ERRORS !
F40PMB: 0 ; PROFILE WORD
XWD 1,5 ; WORDS,,BYTES
SIXBIT /CALL*/
F10PMB: 0 ; PROFILE WORD
XWD 2,10 ; WORDS,,BYTES
SIXBIT /F10CAL/
SIXBIT /L*/
LIT
PRGEND
TITLE NEWSTRING - NEW BYTE STRING ROUTINE
; STRING PROCEDURE NEWSTRING(M,N); VALUE M,N; INTEGER M,N;
.EXIT=1
.M=4
.N=5
SEARCH ALGPRM,ALGSYS
LIBENT(320,NEWSTRING)
XWD 0,5
XWD $PRO!$S!$SIM,3
XWD $VAR!$I!$FOV,.M
XWD $VAR!$I!$FOV,.N
MOVE A0,.N(DL) ; BYTE SIZE
JUMPLE A0,.+2
CAILE A0,^D36 ; 1 <= N <= 36?
SYSER1 15,0 ; NO - COMPLAIN
MOVEI A1,^D36
IDIV A1,A0 ; NUMBER OF BYTES PER WORD
MOVE A0,.M(DL) ; NUMBER OF BYTES REQUIRED
JUMPE A0,NEW1 ; TREAT SPECIAL CASE OF NULL STRING
TLNE A0,777700 ; EXCEEDS MAXIMUM LENGTH?
SYSER1 2,0 ; YES - COMPLAIN
IDIVI A0,(A1)
JUMPE A1,.+2
ADDI A0,1 ; CALCULATE NUMBER OF WORDS REQUIRED
PUSHJ SP,GETCLR ; AND ASK FOR THEM (ZEROED)
MOVEM A1,.EXIT+1(DL) ; SET UP FIRST WORD OF RESULT
HRLZ A0,.N(DL)
LSH A0,6
TLO A0,440000
HLLM A0,.EXIT+1(DL) ; COMPLETE STR1
MOVE A0,.M(DL) ; GET NUMBER OF BYTES
TLO A0,STRDYN!STRPRC ; FLAG STRING DYNAMIC & RESULT OF PROC
MOVEM A0,.EXIT+2(DL) ; AND SET UP SECOND WORD OF RESULT
JRST .EXIT(DL)
NEW1: SETZM .EXIT+2(DL) ; SPECIAL CASE OF A NULL STRING
HRLZ A0,.N(DL)
LSH A0,6
MOVEM A0,.EXIT+1(DL)
JRST .EXIT(DL)
LIT
PRGEND
TITLE LENGTH - LENGTH OF STRING ROUTINE
; INTEGER PROCEDURE LENGTH(S); STRING S;
.EXIT=1
.S=3
SEARCH ALGPRM,ALGSYS
LIBENT(321,LENGTH)
XWD 0,5
XWD $PRO!$I!$SIM,2
XWD $VAR!$S!$FON,.S
XCT .S(DL) ; GET VALUE OF STRING
PUSH SP,A0 ; [256] SAVE STRING ADDRESS
PUSH SP,A1 ; [256] AND SECOND WORD OF HEADER TOO
MOVEI A2,@A2
SKIPN STR1(A2) ; IS THIS A NULL STRING ?
TDZA A0,A0 ; YES - LENGTH IS ZERO
LDB A0,[POINT 24,STR2(A2),35] ; [256] NO - GET ITS LENGTH
MOVEM A0,.EXIT+1(DL) ; [256] STORE RESULT
POP SP,A2 ; [256] RESTORE STRING BITS
POP SP,A1 ; [256] RESTORE STRING ADDRESS
SETZ A0, ; [256] GET READY TO DELETE STRING SPACE
TLC A2,STRDYN!STRPRC; [256] COMPLEMENT STRING STATUS BITS
TLCE A2,STRDYN!STRPRC; [256] WAS THIS A TRANSIENT STRING?
JRST .EXIT(DL) ; [256] NO, EXIT
PUSHJ SP,GETOWN ; [256] YES, DELETE IT
JRST .EXIT(DL)
LIT
PRGEND
TITLE SIZE - BYTE-SIZE OF STRING ROUTINE
; INTEGER PROCEDURE SIZE(S); STRING S;
.EXIT=1
.S=3
SEARCH ALGPRM,ALGSYS
LIBENT(326,SIZE)
XWD 0,5
XWD $PRO!$I!$SIM,2
XWD $VAR!$S!$FON,.S
XCT .S(DL) ; GET VALUE OF STRING
PUSH SP,A0 ; [256] SAVE STRING ADDRESS
PUSH SP,A1 ; [256] AND SECOND WORD OF HEADER TOO
MOVEI A2,@A2 ; [256] STATICISE
LDB A0,[POINT 6,STR1(A2),11] ; [256] GET BYTE-SIZE
MOVEM A0,.EXIT+1(DL) ; [256] & RETURN IT
POP SP,A2 ; [256] RESTORE STRING BITS
POP SP,A1 ; [256] RESTORE STRING ADDRESS
SETZ A0, ; [256] GET READY TO DELETE STRING SPACE
TLC A2,STRDYN!STRPRC; [256] COMPLEMENT STRING STATUS BITS
TLCE A2,STRDYN!STRPRC; [256] WAS THIS A TRANSIENT STRING?
JRST .EXIT(DL) ; [256] NO, EXIT
PUSHJ SP,GETOWN ; [256] YES, DELETE IT
JRST .EXIT(DL)
LIT
PRGEND
TITLE DELETE - DELETE STRING ROUTINE
; PROCEDURE DELETE(S); STRING S;
.EXIT=1
.S=2
SEARCH ALGPRM,ALGSYS
LIBENT(322,DELETE)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$S!$FON,.S
XCT .S(DL) ; GET ADDRESS OF STRING
EDIT (133) ; AVOID STACK-SHIFT PROBLEMS
PUSH SP,A0 ; [256] SAVE STRING ADDRESS
AOS A2 ; [256] [E133]
MOVE A0,@A2 ; [256] [E133]
SOS A2 ; [256] [E133]
TLNN A0,STRDYN ; DYNAMIC?
JRST .EXIT(DL) ; NO - LEAVE THIS ONE
HRRZ A1,@A2
JUMPE A1,DEL2 ; MAKE SURE THERE IS A BYTE STRING
MOVEI A0,0
POP SP,A1 ; [256] RESTORE STRING ADDRESS
PUSH SP,A2 ; SAVE ADDRESS
PUSHJ SP,GETOWN ; DELETE STRING
POP SP,A2 ; RESTORE ADDRESS
DEL2: MOVEI A2,@A2 ; [E133]
SETZM STR1(A2) ; CLEAR BYTE STRING POINTER
SETZM A0,STR2(A2) ; CLEAR SECOND WORD
JRST .EXIT(DL) ; EXIT
LIT
PRGEND
TITLE CONCAT - STRING CONCATENATION ROUTINE
SEARCH ALGPRM,ALGSYS
; STRING PROCEDURE CONCAT(S1,S2,...,Sn); STRING S1,S2,...,Sn;
.EXIT=1
.N=4 ; COUNT OF PARAMETERS
.W=5 ; WHERE IN STACK WE ARE
.F=6
.S=3
DEFINE REP(M,S,I),<
Q=0
V=S-I
REPEAT PRMMAX,<
IF2,<
Q=Q+1
V=V+I>
M(\Q,\V)>>
DEFINE DEC(A,B),<
IF2,<.S'A=B>>
DEFINE PAR(A,B),<
IF1,<BLOCK 1>
IF2,<XWD $VAR!$S!$FON,.S'A>>
REP(DEC,.F,.S)
LIBENT(325,CONCAT,.N)
XWD 0,3*PRMMAX+5 ; PL,,STACK-SIZE
XWD $PRO!$S!$SIM,PRMMAX+1; STRING PROCEDURE
REP(PAR,.F,.S) ; WITH A VARIABLE NUMBER OF PARAMETERS
SOSG A1,.N(DL) ; GET COUNT OF PARAMETERS
SYSER1 10,0 ; NONE - ERROR.
PUSH SP,A1 ; SAVE COUNT OF PARAMETERS
SETZM .EXIT+1(DL) ; INITIALIZE RESULT TO THE
SETZB A0,.EXIT+2(DL) ; NULL STRING
PUSH SP,A0 ; AND SET MAXIMUM BYTE-SIZE TO ZERO
MOVE A0,[XWD DL,.F] ; INITIALIZE INDIRECT POINTER
MOVEM A0,.W(DL) ; IN W
CONCA1: XCT @.W(DL) ; GET A STRING HEADER INTO A0,A1
SKIPN A0 ; IS IT A NULL STRING ?
SETZ A1, ; YES - SET LENGTH TO ZERO
MOVEI A2,@.W(DL) ; GET ACTUAL ADDRESS
MOVEM A0,STR1(A2) ; STORE BYTE POINTER
MOVEM A1,STR2(A2) ; AND LENGTH
LDB A0,[
POINT 6,STR1(A2),11] ; GET BYTE-SIZE INTO A0
LDB A1,[
POINT 24,STR2(A2),35] ; AND LENGTH INTO A1
CAMLE A0,(SP) ; IF THIS BYTE SIZE IS LARGEST
MOVEM A0,(SP) ; SO FAR, REMEMBER IT
ADDB A1,.EXIT+2(DL) ; ADD LENGTH INTO RUNNING TOTAL
MOVEI A2,.S ; THEN STEP .W TO POINT TO
ADDM A2,.W(DL) ; THE NEXT FORMAL PARAMETER
SOSLE .N(DL) ; COUNT DOWN PARAMETER COUNT
JRST CONCA1 ; REPEAT FOR EACH PARAMETER
POP SP,A3 ; GET BYTE-SIZE INTO A3
POP SP,.N(DL) ; AND RESTORE NUMBER OF PARAMETERS
TLO A1,STRDYN!STRPRC; MARK AS DYNAMIC, AND PROCEDURE RESULT
EXCH A1,.EXIT+2(DL) ; SAVE AS STR2 OF RESULT
JUMPE A1,CONCA7 ; RETURN IF LENGTH IS ZERO
MOVE A0,A1 ; GET NUMBER OF BYTES INTO A0
MOVEI A1,^D36 ; FIND OUT HOW MANY BYTES
IDIVI A1,(A3) ; FIT INTO A 36-BIT WORD
ADDI A0,-1(A1) ; AND HENCE HOW MANY WORDS
IDIVI A0,(A1) ; WILL BE NEEDED FOR THE STRING
ROT A3,-^D12 ; SHIFT BYTE-SIZE INTO BITS 6-11
TLO A3,440000 ; SET 'P' FIELD
MOVEM A3,.EXIT+1(DL) ; AND STORE LH OF STR1 OF RESULT
PUSHJ SP,GETCLR ; GET THE SPACE NEEDED
HRRM A1,.EXIT+1(DL) ; AND STORE ADDRESS IN STR1.
MOVE A1,.EXIT+1(DL) ; GET BYTE-POINTER TO RESULT
MOVEI A2,.F(DL) ; GET ADDRESS OF FIRST HEADER
SKIPA A3,.N(DL) ; GET NUMBER OF STRINGS
CONCA2: ADDI A2,.S ; STEP ON TO NEXT STRING
MOVE A4,STR1(A2) ; GET BYTE POINTER TO SOURCE
LDB A5,[
POINT 24,STR2(A2),35] ; GET LENGTH OF STRING
JUMPE A5,CONCA4 ; IGNORE IF NULL STRING
CONCA3: ILDB A0,A4 ; GET BYTE FROM SOURCE STRING
IDPB A0,A1 ; STORE IN DESTINATION STRING
SOJG A5,CONCA3 ; REPEAT FOR ENTIRE STRING
CONCA4: SOJG A3,CONCA2 ; REPEAT FOR EACH STRING
CONCA5: MOVNI A2,.S ; GET SIZE OF ENTRY
ADDB A2,.W(DL) ; COUNT W DOWN TO POINT TO HEADER
MOVEI A2,@A2 ; DELOCATE ADDRESS
MOVEI A1,@STR1(A2) ; GET ADDRESS OF STRING
MOVE A0,STR2(A2) ; GET LENGTH INTO A0
TLZE A0,STRDYN ; IF STRING IS NOT DYNAMIC
TLZN A0,STRPRC ; OR NOT RESULT OF A PROCEDURE
JRST CONCA6 ; LEAVE IT ALONE
TDZE A0,A0 ; CLEAR A0 AND UNLESS ALREADY ZERO
PUSHJ SP,GETOWN ; CALL GETOWN TO RETURN THE SPACE
CONCA6: SOSLE .N(DL) ; COUNT ONE MORE CHECKED
JRST CONCA5 ; REPEAT FOR EACH STRING
CONCA7: JRST .EXIT(DL) ; THEN RETURN
LIT
PRGEND
TITLE INSYMBOL - INPUT SYMBOL ROUTINE
; PROCEDURE INSYMBOL(I); INTEGER I;
.EXIT=1
.I=2
SEARCH ALGPRM,ALGSYS
LIBENT(401,INSYMBOL)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FON,.I
XCT 1,.I(DL) ; GET ADDRESS OF I
PUSH SP,A2
JSP AX,INCHAR ; INPUT CHARACTER
MOVE A0,A13
POP SP,A2 ; RESTORE ADDRESS.
XCT .I+1(DL) ; AND STORE IN I
JRST .EXIT(DL)
LIT
PRGEND
TITLE OUTSYMBOL - OUTPUT SYMBOL ROUTINE
; PROCEDURE OUTSYMBOL(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(402,OUTSYMBOL)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVE A13,.N(DL) ; GET BYTE
MOVEI AX,.EXIT(DL)
JRST OUCHAR ; AND OUTPUT IT
LIT
PRGEND
TITLE NEXTSYMBOL - NEXT SYMBOL ROUTINE
; PROCEDURE NEXTSYMBOL(I); INTEGER I;
.EXIT=1
.I=2
SEARCH ALGPRM,ALGSYS
LIBENT(403,NEXTSYMBOL)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FON,.I
;
; Edit(1015) Evaluate parameter by NAME correctly.
;
XCT 1,.I(DL) ; [E1015] Get address of I
PUSH SP,A2 ; [E1015] Save over NXTBYT
PUSHJ SP,NXTBYT ; GET NEXT BYTE
IOERR 6,(A13) ; EOF - CHAN # IN A13
MOVE A0,A13 ; [E1015] Not EOF - byte in A13
POP SP,A2 ; [E1015] Get back address of I
XCT .I+1(DL) ; AND STORE IN I
JRST .EXIT(DL)
LIT
PRGEND
TITLE SKIPSYMBOL - SKIP SYMBOL ROUTINE
; PROCEDURE SKIPSYMBOL;
.EXIT=1
SEARCH ALGPRM,ALGSYS
LIBENT(404,SKIPSYMBOL)
XWD 0,1
XWD $PRO!$N!$SIM,1
MOVEI AX,.EXIT(DL)
JRST INCHAR ; INPUT BYTE AND IGNORE IT
LIT
PRGEND
TITLE BREAKOUTPUT - BREAK OUTPUT ROUTINE
; PROCDURE BREAKOUTPUT;
.EXIT=1
SEARCH ALGPRM,ALGSYS
LIBENT(405,BREAKOUTPUT)
XWD 0,1
XWD $PRO!$N!$SIM,1
MOVEI AX,.EXIT(DL)
JRST BRKCHR ; BREAK OUTPUT
LIT
PRGEND
TITLE SPACE - SPACE ROUTINE
; PROCEDURE SPACE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
.V=3
SEARCH ALGPRM,ALGSYS
LIBENT(406,SPACE,.V)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A0,1 ; SET DEFAULT
SOSE .V(DL) ; ANY ARGUMENT
MOVE A0,.N(DL) ; YES - GET IT
JUMPLE A0,SPACE2 ; IGNORE IF <= 0
SPACE1: MOVEI A13," "
JSP AX,OUCHAR ; OUTPUT SPACE
SOJN A0,SPACE1 ; REPEAT UNTIL FINISHED
SPACE2: JRST .EXIT(DL)
LIT
PRGEND
TITLE TAB - TAB ROUTINE
; PROCEDURE TAB(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
.V=3
SEARCH ALGPRM,ALGSYS
LIBENT(407,TAB,.V)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A0,1 ; SET DEFAULT
SOSE .V(DL) ; ANY ARGUMENT?
MOVE A0,.N(DL) ; YES - GET IT
JUMPLE A0,TAB2 ; IGNORE IF <= 0
TAB1: MOVEI A13," "
JSP AX,OUCHAR ; OUTPUT TAB
SOJN A0,TAB1 ; REPEAT UNTIL FINISHED
TAB2: JRST .EXIT(DL)
LIT
PRGEND
TITLE NEWLINE - NEWLINE ROUTINE
; PROCEDURE NEWLINE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
.V=3
SEARCH ALGPRM,ALGSYS
LIBENT(410,NEWLINE,.V)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A0,1 ; SET DEFAULT
SOSE .V(DL) ; ANY ARGUMENT
MOVE A0,.N(DL) ; YES - GET IT
JUMPLE A0,NEWL2 ; IGNORE IF <= 0
NEWL1: MOVEI A13,CR
JSP AX,OUCHAR ; CARRIAGE RETURN
MOVEI A13,LF
JSP AX,OUCHAR ; LINE FEED
SOJN A0,NEWL1 ; REPEAT UNTIL FINISHED
TLNE A11,TTYDEV ; TTY TYPE DEVICE?
JSP AX,BRKCHR ; YES - BREAK OUTPUT
NEWL2: JRST .EXIT(DL)
LIT
PRGEND
TITLE PAGE - PAGE ROUTINE
; PROCEDURE PAGE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
.V=3
SEARCH ALGPRM,ALGSYS
LIBENT(411,PAGE,.V)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A13,CR
JSP AX,OUCHAR ; CARRIAGE RETURN
MOVEI A0,1 ; SET DEFAULT
SOSE .V(DL) ; ANY ARGUMENT
MOVE A0,.N(DL) ; YES - GET IT
JUMPLE A0,PAGE2 ; IGNORE IF <= 0
PAGE1: MOVEI A13,FF
JSP AX,OUCHAR ; FORM FEED
SOJN A0,PAGE1 ; REPEAT UNTIL FINISHED
TLNE A11,TTYDEV ; TTY TYPE DEVICE?
JSP AX,BRKCHR ; YES - BREAK OUTPUT
PAGE2: JRST .EXIT(DL)
LIT
PRGEND
TITLE READ - READ ROUTINE
; PROCEDURE READ(A); (INTEGER/REAL/LONG REAL/BOOLEAN/STRING) A;
SEARCH ALGPRM,ALGSYS
DEFINE REP(M,A,I)
<Q=0
R=A-I
REPEAT PRMMAX, <
IF2,
<Q=Q+1
R=R+I>
M \Q,\R>>
DEFINE DECL(A,B)
<IF2, <.WV'A=B>>
DEFINE PAR(A,B)
<IF1, <Z>
IF2, <XWD $VAR!$WV!$FON,.WV'A>>
.EXIT=1
.V1=2
.V2=3
.CH=4
REP DECL,5,3
LIBENT(412,READ,.V1)
XWD 0,3*PRMMAX+4
XWD $PRO!$N!$SIM,PRMMAX+1
REP PAR,5,3
SOSN A5,.V1(DL) ; CHECK NUMBER OF PARAMETERS
SYSER1 10,0 ; NONE
MOVE A1,PRGLNK(DL) ; GET PROGRAM LINK
SUBI A1,1(A5) ; MOVE BEFORE FIRST ACTUAL PARAMETER
MOVEM A1,.V1(DL) ; AND SAVE IN V1
MOVN A5,A5
HRLZI A5,(A5)
HRRI A5,.WV1(DL) ; MAKE COUNTER/POINTER TO FORMALS
SUBI A5,(DB) ; AND DELOCATE IT
READ12: MOVEM A5,.V2(DL) ; UPDATE FORMAL POINTER
AOS A1,.V1(DL) ; UPDATE ACTUAL POINTER
HLRZ A0,@A1
ANDI A0,$D!$KIND!$TYPE!$STAT
CAIN A0,$D!$VAR!$S!$REG
; DYNAMIC VARIABLE REGULAR STRING?
JRST READ3 ; YES - BYTE
ANDI A0,$TYPE ; GET TYPE
CAIN A0,$S
JRST READ4 ; STRING
MOVEI A2,2 ; SET UP FOR LONG REAL
CAIN A0,$LR
JRST READ1 ; LONG REAL
CAIE A0,$R
READ3: TDZA A2,A2 ; INTEGER/BOOLEAN
MOVEI A2,1 ; REAL
READ1: PUSH SP,A2 ; SAVE READ MODE
MOVE A5,.V2(DL) ; GET ADDRESS OF NEXT FORMAL
ADDI A5,(DB)
XCT 1,(A5)
EXCH A2,(SP) ; AND EXCHANGE THEM
PUSHJ SP,READ. ; READ NUMBER
JOV READOV ; [E060] TRAP OVERFLOW
MOVEM A13,.CH(DL) ; SAVE TERMINATOR
READ2: POP SP,A2 ; RESTORE ADDRESS OF PARAMETER
AOS A5,.V2(DL) ; INCREMENT FORMAL ADDRESS
ADDI A5,(DB)
XCT (A5) ; AND STORE RESULT
READ13: AOS A5,.V2(DL)
AOBJN A5,READ12 ; CARRY ON IF MORE ACTUALS
JRST READ15
READ4: MOVE AX,.V2(DL) ; GET FORMAL ADDRESS
ADDI AX,(DB) ; RELOCATE IT
XCT 1,(AX) ; GET ADDRESS OF STRING
PUSH SP,A2 ; AND SAVE IT ON THE STACK
JSP AX,INCHAR ; GET NEXT SYMBOL
CAIE A13,"""" ; IS IT A QUOTE ?
JRST .-2 ; NO - IGNORE IT
SETZB A0,A1 ; YES - CLEAR COUNT
MOVSI A2,(POINT 7,0) ; AND INITIALIZE BYTE POINTER
READ5: JSP AX,INCHAR ; READ NEXT CHAR
CAIE A13,"""" ; IS THIS ANOTHER QUOTE ?
JRST READ6 ; NO - DATA CHARACTER
;
; Edit(1017) Don't lose the character after end of string.
;
PUSHJ SP,NXTBYT ; [E1017] Look at next character.
IOERR 6,(A13) ; [E1017] EOF - channel # in A13.
CAIE A13,"""" ; [E1017] Is it a quote too ?
JRST READ8 ; [E1017] No - so end of string
JSP AX,INCHAR ; [E1017] Yes - advance byte pointer
READ6: TLNE A2,760000 ; FILLED A COMPLETE WORD ?
JRST READ7 ; NO
EXCH A0,(SP) ; YES - SAVE IT ON THE STACK
PUSH SP,A0 ; REPLACE STRING HEADER ADDRESS
MOVSI A2,(POINT 7,A0) ; RESET BYTE POINTER
SETZ A0, ; AND CLEAR JUNK AGAIN
READ7: IDPB A13,A2 ; STORE CHARACTER INTO A0
AOJA A1,READ5 ; COUNT IT AND LOOP
READ8: SETZM .CH(DL) ; [E1017] Don't gobble a CR in this case
SKIPN A2,A1 ; GET COUNT OF CHARACTERS
JRST READ9 ; NONE - NULL STRING
EXCH A0,(SP) ; PUSH LAST WORD OF STRING
PUSH SP,A0 ; AND REPLACE HEADER ADDRESS
ADDI A2,4 ; ROUND UP NUMBER OF CHARACTERS
IDIVI A2,5 ; CONVERT TO NUMBER OF WORDS
MOVNI A0,-1(A2) ; GET -(# OF WORDS)
ADDI A0,-1(SP) ; GET BASE ADDRESS
SUBI A0,(DB) ; DELOCATE IT
HRLI A0,(<POINT 7,0(DB)>); AND FORM BYTE POINTER
HRLI A2,(A2) ; GET COUNT IN L.H. OF A2 ALSO
READ9: EXCH A2,(SP) ; SAVE COUNT, GET HEADER ADDRESS
MOVE AX,.V2(DL) ; GET FORMAL ADDRESS
ADDI AX,(DB) ; RELOCATE IT
XCT 1(AX) ; OVERWRITE STRING
POP SP,A2 ; RESTORE COUNT
SUB SP,A2 ; ADJUST THE STACK
READ14: MOVE A5,.V2(DL)
ADDI A5,2
AOBJN A5,READ12 ; CARRY ON IF MORE
READ15: MOVE A13,.CH(DL) ; GET TERMINATOR
CAIN A13,15 ; AND IF <CR>
JSP AX,INCHAR ; IGNORE <LF>
JRST .EXIT(DL)
EDIT(060); Trap fixed point overflow on data input
READOV: HLRZ A1,%CHAN(DB) ; [E060] GET CHANNEL NUMBER
IOERR 11,(A1) ; [E060] CAUSE CORRECT ERROR
LIT
PRGEND
TITLE INLINE - READ NEXT LINE FROM INPUT
; INTEGER PROCEDURE INLINE(S); STRING(S);
.EXIT=1
.CHAR=2
.S=3
SEARCH ALGPRM,ALGSYS
LIBENT(433,INLINE)
XWD 0,5
XWD $PRO!$I!$SIM,2
XWD $VAR!$S!$FON,.S
XCT 1,.S(DL) ; GET ADDRESS OF STRING
PUSH SP,A2 ; SAVE IT ON THE STACK
SETZB A0,A1 ; CLEAR COUNT
MOVSI A2,(POINT 7,A0) ; SET A2 TO A BYTE POINTER
INLIN1: JSP AX,INCHR0 ; [E145] READ NEXT CHARACTER
CAIL A13,40 ; CONTROL CHAR ?
JRST INLIN4 ; NO - ACCEPT IT
CAIN A13,15 ; CARRIAGE RETURN ?
JRST INLIN1 ; YES - IGNORE IT
CAIG A13,14 ; IS IT A TERMINATOR
CAIG A13,11 ; (FF=14, VT=13, LF=12)
JRST INLIN3 ; NO - ACCEPT CHAR
MOVEM A13,.CHAR(DL) ; SAVE TERMINATOR
SKIPN A2,A1 ; ANY CHARACTERS READ ?
JRST INLIN2 ; NO - EASY
EXCH A0,(SP) ; YES - STORE FINAL WORD
PUSH SP,A0 ; REPLACE HEADER ADDRESS
ADDI A2,4 ; ROUND UP CHAR COUNT
IDIVI A2,5 ; CONVERT TO # OF WORDS
MOVNI A0,-1(A2) ; GET -(# OF WORDS)
ADDI A0,-1(SP) ; GET BASE ADDRESS
SUBI A0,(DB) ; DELOCATE IT
HRLI A0,(<POINT 7,0(DB)>); AND FORM BYTE POINTER
HRLI A2,(A2) ; COPY COUNT TO L.H. OF A2
INLIN2: EXCH A2,(SP) ; SAVE COUNT, GET HEADER ADDRESS
XCT .S+1(DL) ; WRITE NEW STRING
POP SP,A2 ; RESTORE COUNT
SUB SP,A2 ; TIDY UP THE STACK
JRST .EXIT(DL) ; AND EXIT
INLIN3: CAIN A13,33 ; ALTMODE ?
JRST INLIN5 ; YES
CAIN A13,11 ; OR TAB ?
JRST INLIN6 ; YES
MOVSI A13,100(A13) ; NO - SAVE CONTROL CHAR
HRRI A13,"^" ; GET UP-ARROW
JSP AX,INLIN7 ; PLACE IN BUFFER
HLRZ A13,A13 ; GET CHAR AGAIN
INLIN4: CAIE A13,"[" ; IF CHARACTER IS A SQUARE
CAIN A13,"]" ; BRACKET (SPECIAL CASE)
JSP AX,INLIN7 ; PUT IT IN TWICE
CAIL A13,175 ; IS IT AN ESCAPE ?
INLIN5: MOVEI A13,"$" ; YES - SUBSTITUTE DOLLAR
INLIN6: MOVEI AX,INLIN1 ; SET TRANSFER ADDRESS
INLIN7: TLNE A2,760000 ; FILLED A COMPLETE WORD ?
JRST INLIN8 ; NO
EXCH A0,(SP) ; YES - PLACE IT ON THE STACK
PUSH SP,A0 ; REPLACE HEADER ADDRESS
MOVSI A2,(POINT 7,A0) ; AND RESET BYTE POINTER
SETZ A0, ; CLEAR JUNK CHARS
INLIN8: IDPB A13,A2 ; STORE CHARACTER IN A0
AOJA A1,(AX) ; AND GO READ NEXT
LIT
PRGEND
TITLE WRITE - WRITE STRING ROUTINE
; PROCEDURE WRITE(S); STRING(S);
.EXIT=1
.S=2
SEARCH ALGPRM,ALGSYS
LIBENT(413,WRITE)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$S!$FON,.S
XCT .S(DL) ; GET ARGUMENT
PUSH SP,A0 ; [256] SAVE STRING ADDRESS
PUSH SP,A1 ; [256] AND SECOND WORD OF HEADER TOO
MOVEI A4,0 ; CLEAR SPECIAL MODE FLAG
MOVEI AX,WRIT5 ; SET LINK
WRIT1: MOVE A3,STR1(A0) ; [237] GET BYTE-POINTER
LDB A1,[POINT 24,STR2(A0),35] ; [237] GET STRING LENGTH
WRIT2: SOJL A1,WRIT3 ; [256] DECREMENT BYTE COUNT - EXHAUSTED?
ILDB A13,A3 ; NO - LOAD UP BYTE
JUMPE A13,WRIT2 ; IGNORE NULLS
JRST (AX)
WRIT3: POP SP,A2 ; [256] RESTORE STRING BITS
POP SP,A1 ; [256] RESTORE STRING ADDRESS
SETZ A0, ; [256] GET READY TO DELETE STRING SPACE
TLC A2,STRDYN!STRPRC; [256] COMPLEMENT STRING STATUS BITS
TLCE A2,STRDYN!STRPRC; [256] WAS THIS A TRANSIENT STRING?
JRST .EXIT(DL) ; [256] NO, EXIT
PUSHJ SP,GETOWN ; [256] YES, DELETE IT
JRST .EXIT(DL) ; [256] AND EXIT
WRIT4: JSP AX,WRIT2 ; GET NEXT BYTE
WRIT5: CAIN A13,"[" ; LEFT SQUARE BRACKET?
XCT [
AOJA A4,WRIT4
AOJA A4,WRIT4
SOJA A4,WRIT6]+1(A4)
CAIN A13,"]" ; NO - RIGHT SQUARE BRACKET?
XCT [
AOJA A4,WRIT6
SOJA A4,WRIT4
SOJA A4,WRIT6]+1(A4)
XCT [
AOJA A4,WRIT6
JRST WRIT6
JRST WRIT8]+1(A4) ; NO
WRIT6: MOVEI AX,WRIT4
JRST OUCHAR ; OUTPUT CHARACTER
WRIT7: TDZA A5,A5 ; CLEAR COUNT (SUBSEQUENT TIMES)
WRIT8: TDZA A5,A5 ; CLEAR COUNT (FIRST TIME)
WRIT9: JSP AX,WRIT2 ; GET NEXT CHARACTER
CAIL A13,"0"
CAIL A13,"0"+^D10 ; DIGIT?
JRST WRIT11 ; NO
JUMPL A5,WRIT9 ; YES - IGNORE IF OVERFLOWED
IMULI A5,^D10 ; MULTIPLY BY TEN
JOV WRIT10 ; AND CHECK FOR OVERFLOW
ADDI A5,-"0"(A13) ; ADD IN DIGIT
JOV WRIT10 ; AND CHECK AGAIN
JRST WRIT9 ; CARRY ON
WRIT10: MOVNI A5,1 ; FLAG OVERFLOW
JRST WRIT9
WRIT11: CAIN A13,"]" ; RIGHT SQUARE BRACKET?
SOJA A4,WRIT4 ; YES
JUMPG A5,WRIT12 ; NO - GOT A NUMBER?
AOJE A5,WRIT9 ; NO - SORT IT OUT
WRIT12: ANDI A13,137 ; CONVERT LOWER CASE TO UPPER
CAIN A13,"S"
JRST WRIT18 ; SPACE
CAIN A13,"T"
JRST WRIT17 ; TAB
CAIN A13,"P"
JRST WRIT15 ; PAGE
CAIE A13,"C"
CAIN A13,"N"
JRST WRIT13 ; NEWLINE
CAIE A13,"B"
JRST WRIT7 ; RUBBISH
JRST WRIT20 ; BREAK
WRIT13: MOVEI A13,CR ; NEWLINE
JSP AX,OUCHAR
MOVEI A13,LF
JSP AX,OUCHAR
SOJG A5,WRIT13
WRIT14: TLNE A11,TTYDEV ; TTY TYPE DEVICE?
WRIT20: JSP AX,BRKCHR ; YES - BREAK OUTPUT
JRST WRIT9
WRIT15: MOVEI A13,CR ; PAGE
JSP AX,OUCHAR
MOVEI A13,LF
JSP AX,OUCHAR
WRIT16: MOVEI A13,FF
JSP AX,OUCHAR
SOJG A5,WRIT16
JRST WRIT14
WRIT17: SKIPA A7,[" "] ; TAB
WRIT18: MOVEI A7," " ; SPACE
WRIT19: MOVE A13,A7
JSP AX,OUCHAR
SOJG A5,WRIT19
JRST WRIT9
LIT
PRGEND
TITLE PRINT NUMBER ROUTINE
; PROCEDURE PRINT(I,M,N); VALUE I,M,N; INTEGER I,M,N;
; PROCEDURE PRINT(X,M,N); VALUE X,M,N; REAL X; INTEGER M,N;
; PROCEDURE PRINT(D,M,N); VALUE D,M,N; LONG REAL D; INTEGER M,N;
.EXIT=1
.IXD=2
.M=4
.N=5
.V=6
SEARCH ALGPRM,ALGSYS
LIBENT(414,PRINT,.V)
XWD 0,6
XWD $PRO!$N!$SIM,4
XWD $VAR!$WA!$FOV,.IXD
XWD $VAR!$I!$FOV,.M
XWD $VAR!$I!$FOV,.N
SOSE A5,.V(DL)
JRST PRIN1(A5) ; BRANCH ON NUMBER OF PARAMETERS
PRIN1: SYSER1 10,0 ; 0
SETZM .M(DL) ; 1
SETZM .N(DL) ; 2
MOVM A3,.M(DL)
MOVM A4,.N(DL) ; GET M,N
EDIT(103); Allow for stacked call to PRINT
MOVEI A1,@PRGLNK(DL) ; [E103] GET PROGRAM LINK
SUBI A1,(A5) ; AND LOCATE FIRST PARAMETER
HLRZ A0,(A1)
ANDI A0,$D!$KIND!$TYPE!$STAT
MOVEI A2,1 ; SET REAL MODE
CAIN A0,$D!$VAR!$S!$REG
; DYNAMIC VARIABLE REGULAR STRING?
SOJA A2,PRIN2 ; YES - BYTE
ANDI A0,$TYPE ; GET ITS TYPE
CAIN A0,$I
SOJA A2,PRIN2 ; INTEGER
CAIN A5,2 ; TWO PARAMETERS?
EXCH A3,A4 ; YES - SWAP M AND N
CAIE A0,$R
MOVEI A2,2 ; LONG REAL
PRIN2: DMOVE A0,.IXD(DL) ; LOAD UP FIRST PARAMETER
PUSHJ SP,PRINT. ; AND PRINT IT
JRST .EXIT(DL)
LIT
PRGEND
TITLE READOCTAL - READ OCTAL ROUTINE
; PROCEDURE READOCTAL(A); (INTEGER/REAL/LONG REAL/BOOLEAN) A;
.EXIT=1
.A=2
SEARCH ALGPRM,ALGSYS
LIBENT(415,READOCTAL)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$AB!$FON,.A
XCT 1,.A(DL) ; GET ADDRESS OF A
PUSH SP,A2 ; AND SAVE IT
MOVE A1,PRGLNK(DL) ; GET PROGRAM LINK
HLRZ A0,-1(A1)
ANDI A0,$TYPE ; GET TYPE
CAIN A0,$LR ; LONG REAL?
JRST RDOCT3 ; YES
RDOCT1: PUSHJ SP,RDOCT ; READ OCTAL NUMBER
RDOCT2: POP SP,A2 ; RESTORE ADDRESS OF A
XCT .A+1(DL) ; AND STORE RESULT
JRST .EXIT(DL)
RDOCT3: PUSHJ SP,RDOCT ; READ HIGH ORDER WORD
PUSH SP,A0 ; AND SAVE IT
PUSHJ SP,RDOCT ; READ LOW ORDER WORD
MOVE A1,A0
POP SP,A0 ; RESTORE LOW ORDER WORD
JRST RDOCT2
LIT
PRGEND
TITLE PRINTOCTAL - PRINT OCTAL ROUTINE
; PROCEDURE PRINTOCTAL(A); VALUE A; (INTEGER/REAL/LONG REAL/BOOLEAN) A;
.EXIT=1
.A=2
SEARCH ALGPRM,ALGSYS
LIBENT(416,PRINTOCTAL)
XWD 0,4
XWD $PRO!$N!$SIM,2
XWD $VAR!$AB!$FOV,.A
MOVE A1,.A(DL) ; GET VALUE OF A
MOVE A2,PRGLNK(DL) ; GET PROGRAM LINK
HLRZ A2,-1(A2)
ANDI A2,$TYPE ; GET TYPE
CAIN A2,$LR ; LONG REAL?
JRST PROCT1 ; YES
PUSHJ SP,PROWD ; NO - PRINT WORD
JRST .EXIT(DL)
PROCT1: PUSH SP,.A+1(DL) ; SAVE LOW ORDER WORD
PUSHJ SP,PROWD ; PRINT HIGH ORDER WORD
MOVEI A13," "
JSP AX,OUCHAR ; SPACE
POP SP,A1 ; RESTORE LOW ORDER WORD
PUSHJ SP,PROWD ; AND PRINT IT
JRST .EXIT(DL)
PROWD: MOVEI A13,"%" ; PRINT OCTAL WORD
JSP AX,OUCHAR ; "%"
MOVS A1,A1
PUSHJ SP,PROCT ; PRINT HIGH HALF WORD
MOVS A1,A1
JRST PROCT ; PRINT LOW HALF WORD
LIT
PRGEND
TITLE INPUT/OUTPUT - INPUT/OUTPUT CHANNEL ROUTINES
; PROCEDURE INPUT(N,S,M,B,L); VALUE N,M,B,L; INTEGER N,M,B; STRING S; LABEL L;
; PROCEDURE OUTPUT(N,S,M,B,L); VALUE N,M,B,L; INTEGER N,M,B; STRING S; LABEL L;
.EXIT=1
.IO=2 ; IO FLAG
.N=3 ; CHANNEL NUMBER
.S=4 ; DEVICE NAME/LOGICAL STRING
.M=7 ; MODE
.B=10 ; NUMBER OF BUFFERS
.L=11
.V=14
SEARCH ALGPRM,ALGSYS
LIBENT(417,INPUT,.V)
XWD 0,14
XWD $PRO!$N!$SIM,6
XWD $VAR!$I!$FOV,.N
XWD $VAR!$S!$FON,.S
XWD $VAR!$IB!$FOV,.M
XWD $VAR!$I!$FOV,.B
XWD $VAR!$L!$FOV,.L
SETZM .IO(DL) ; FLAG AS INPUT
JRST IO1
LIBENT(420,OUTPUT,.V)
XWD 0,14
XWD $PRO!$N!$SIM,6
XWD $VAR!$I!$FOV,.N
XWD $VAR!$S!$FON,.S
XWD $VAR!$IB!$FOV,.M
XWD $VAR!$I!$FOV,.B
XWD $VAR!$L!$FOV,.L
MOVEI A0,1
MOVEM A0,.IO(DL) ; FLAG AS OUTPUT
IO1: SOSE A1,.V(DL)
IO2: JRST IO2(A1) ; BRANCH ON NUMBER OF PARAMETERS
SYSER1 10,0 ; 0,1
SETZM .M(DL) ; 2
SETZM .B(DL) ; 3
SETZM .L(DL) ; 4
SKIPL A1,.N(DL) ; GET CHANNEL NUMBER
CAIL A1,40 ; 0 <= N < 40?
IOERR 14,(A1) ; NO - COMPLAIN
CAIGE A1,20 ; LOGICAL CHANNEL?
JRST IO3 ; NO
XCT 1,.S(DL) ; YES - GET ADDRESS OF STRING
MOVE A0,A2
MOVE A1,.N(DL) ; RESTORE CHANNEL NUMBER
MOVE A2,.IO(DL)
PUSHJ SP,INPT(A2) ; AND OPEN LOGICAL DEVICE
JRST IO6 ; [E124] GO TEST FOR ERRORS
IO3: XCT .S(DL) ; PHYSICAL DEVICE - GET STRING ADDRESS
MOVEI A2,@A2 ; STATICISE IT
LDB A0,[
POINT 24,STR2(A2),35] ; GET ITS LENGTH
CAIL A0,6
MOVEI A0,6 ; ONLY SIX BYTES REQUIRED
JUMPE A0,IO5 ; NO NAME - FAILS LATER ON
MOVE A5,A0 ; BYTE INDEX
MOVEI A0,0 ; NAME ACCUMULATOR
MOVSI A6,(POINT 6,A0,)
; SET UP BYTE POINTER
MOVEI A7,1 ; BYTE NUMBER
MOVE A4,STR1(A2) ; GET BYTE POINTER TO STRING
IO4: ILDB A2,A4 ; LOAD BYTE
SUBI A2,40
JUMPL A2,IO5 ; TOO LOW
CAILE A2,132
JRST IO5 ; TOO HIGH
CAIL A2,100 ; LOWER CASE ALPHA?
SUBI A2,40 ; YES - RECODE TO UPPER CASE ALPHA
IDPB A2,A6 ; INSERT SIXBIT BYTE
CAIE A7,(A5) ; FINISHED?
AOJA A7,IO4 ; NO
IO5: MOVE A1,.N(DL) ; GET CHANNEL NUMBER
HRL A1,.B(DL) ; GET NUMBER OF BUFFERS
MOVE A2,.M(DL) ; GET MODE
MOVE A3,.IO(DL)
PUSHJ SP,INPT(A3) ; AND GO TO INPT OR OUTPT
EDIT(124); Remember A1 not preserved !
IO6: JUMPE A1,.EXIT(DL) ; [E124] RETURN IF NO ERROR
MOVEM A1,.IO(DL) ; [E124] OTHERWISE SAVE IOERR
SKIPE A2,.L(DL) ; IF HE GAVE AN ERROR-LABEL
XCT .L(DL) ; ELABORATE IT
JUMPN A2,(A2) ; GOTO ERR (UNLESS IT'S AN OUT OF RANGE SWITCH)
XCT .IO(DL) ; [E124] OTHERWISE REPORT ERROR
LIT
PRGEND
TITLE SELIN/SELOUT - SELECT INPUT/OUTPUT ROUTINES
; PROCEDURE SELECTINPUT(N); VALUE N; INTEGER N;
; PROCEDURE SELECTOUTPUT(N); VALUE N; INTEGER N;
.EXIT=1
.IO=2
.N=3
SEARCH ALGPRM,ALGSYS
LIBENT(421,SELECTINPUT)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A3,0 ; FLAG AS SELIN
JRST SEL1
LIBENT(422,SELECTOUTPUT)
XWD 0,3
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
MOVEI A3,1 ; FLAG AS SELOUT
SEL1: MOVE A1,.N(DL) ; GET ARGUMENT
CAML A1,[-1]
CAIL A1,40 ; -1 <= N < 40?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,SELIN(A3) ; YES - SELECT RELEVANT INPUT/OUTPUT CHANNEL
JRST .EXIT(DL)
LIT
PRGEND
TITLE INCHAN/OUTCHAN - INPUT/OUTPUT CHANNEL ROUTINES
; INTEGER PROCEDURE INCHAN;
; INTEGER PROCEDURE OUTCHAN;
.EXIT=1
.IO=2
SEARCH ALGPRM,ALGSYS ; SEARCH PARAMETER-FILE.
LIBENT(316,INCHAN)
XWD 0,2
XWD $PRO!$I!$SIM,1
MOVEI A1,0 ; FLAG AS INCHAN
JRST INCH1
LIBENT(317,OUTCHAN)
XWD 0,2
XWD $PRO!$I!$SIM,1
MOVEI A1,1 ; FLAG AS OUTCHAN
INCH1: XCT [
HLRE A0,%CHAN(DB)
HRRE A0,%CHAN(DB)](A1)
MOVEM A0,.IO(DL) ; CURRENT INPUT/OUTPUT CHANNEL
JRST .EXIT(DL)
LIT
PRGEND
TITLE RELEASE - RELEASE ROUTINE
; PROCEDURE RELEASE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(423,RELEASE)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPL A1,.N(DL) ; GET ARGUMENT
CAIL A1,40 ; 0 <= N < 40?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,RELESE ; YES - RELEASE RELEVANT CHANNEL
IOERR 13,(A1) ; CHANNEL NOT IN USE
JRST .EXIT(DL)
LIT
PRGEND
TITLE OPENFILE - OPEN FILE ROUTINE
; PROCEDURE OPENFILE(N,S,P,PP,L,I); VALUE N,P,PP,L; INTEGER N,I; STRING S;
; LABEL L; BOOLEAN P,PP;
.EXIT=1
.N=2
.S=3
.P=6
.PP=7
.L=10
.I=13
.LU=16
.V=17
SEARCH ALGPRM,ALGSYS
LIBENT(424,OPENFILE,.V)
XWD 0,17
XWD $PRO!$N!$SIM,7
XWD $VAR!$I!$FOV,.N
XWD $VAR!$S!$FON,.S
XWD $VAR!$IB!$FOV,.P
XWD $VAR!$IB!$FOV,.PP
XWD $VAR!$L!$FOV,.L
XWD $VAR!$I!$FON,.I
SOSE A1,.V(DL)
OPF0: JRST OPF0(A1) ; BRANCH ON NUMBER OF PARAMETERS
SYSER1 10,0 ; 0,1
SETZM .P(DL) ; 2
SETZM .PP(DL) ; 3
SETZM .L(DL) ; 4
SETZM .I(DL) ; 5
SKIPL A1,.N(DL) ; GET CHANNEL NUMBER
CAIL A1,20 ; 0 <= N < 20?
IOERR 14,(A1) ; NO - COMPLAIN
XCT .S(DL) ; GET ADDRESS OF STRING
MOVEM A2,.LU(DL) ; AND SAVE IT
SKIPE A2,.L(DL) ; IF HE GAVE A LABEL
XCT .L(DL) ; EVALUATE IT
PUSH SP,A2 ; AND SAVE IT
SKIPE .I(DL) ; IF HE GAVE A STATUS-WORD
XCT 1,.I(DL) ; EVALUATE ITS ADDRESS
PUSH SP,A2 ; AND SAVE THAT
MOVE A2,.LU(DL) ; RESTORE ADDRESS OF STRING
MOVEI A2,@A2 ; STATICISE IT
LDB A0,[POINT 24,STR2(A2),35] ; GET STRING LENGTH
MOVE A4,STR1(A2) ; AND SAVE BYTE PTR.
SETZB A5,A6 ; CLEAR FILE AND EXTENSION
JUMPE A0,OPF5 ; NULL STRING?
MOVE A7,[POINT 6,A5,]; BYTE POINTER FOR FILE NAME
MOVEI A10,1 ; BYTE INDEX
OPF1: PUSHJ SP,OPF6 ; GET NEXT BYTE
CAIN A2,'.' ; POINT?
AOJA A10,OPF3 ; YES
IDPB A2,A7 ; PLANT BYTE IN NAME
CAIGE A10,6 ; NAME FULL?
AOJA A10,OPF1 ; NO - KEEP GOING
AOJ A10, ; [210] COUNT THE SIXTH CHARACTER
OPF2: PUSHJ SP,OPF6 ; SCAN FOR POINT
CAIE A2,'.'
AOJA A10,OPF2
ADDI A10,1
OPF3: MOVE A7,[POINT 6,A6,]; BYTE POINTER FOR FILE EXTENSION
MOVEI A11,3 ; BYTE COUNT
OPF4: PUSHJ SP,OPF6 ; GET NEXT BYTE
IDPB A2,A7 ; AND PLANT IT IN EXTENSION
SOJE A11,OPF5 ; ANY MORE EXTENSION?
AOJA A10,OPF4 ; NO - KEEP GOING
EDIT(036); FIX STACK ON RETURN FROM OPF6
OPF5A: POP SP,(SP) ; [E037] STEP BACK OVER RETURN ADDRESS
OPF5: MOVE A1,.N(DL) ; RESTORE CHANNEL NUMBER
DMOVE A2,A5 ; LOAD FILE NAME AND EXTENSION
HRLZ A4,.P(DL)
LSH A4,11 ; PROTECTION
MOVE A5,.PP(DL) ; PROJECT-PROGRAMMER
PUSHJ SP,OPFILE ; AND OPEN FILE
POP SP,A2 ; GET ADDR OF I (OR 0)
SKIPN A0, ; ERROR ?
EDIT(160); Don't clobber label address when storing error code.
JRST [POP SP,(SP) ; [E160]
JRST .EXIT(DL)] ; [E160]
SUBI A0,100 ; ERR-CODE HAS 100 ADDED TO IT BY OTS
SKIPE .I(DL) ; YES - I ?
XCT .I+1(DL) ; YES - PUT ERROR-CODE IN IT
POP SP,A2 ; [E160] Get label address
EDIT(020) ; FORLAB NEEDS ADDRESS IN A2, NOT A3 !
SKIPE A2 ; [E020][E160] IS THERE AN ERROR EXIT ?
JRST (A2) ; [E020] IF SO, TAKE IT
IOERR 5,(A1) ; ELSE GIVE ERROR MESSAGE
OPF6: CAMLE A10,A0 ; GET SIXBIT BYTE SUBROUTINE
JRST OPF5A ; [E037] NONE LEFT - ERROR RETURN
ILDB A2,A4 ; AND GET NEXT BYTE
SUBI A2,40
JUMPL A2,OPF7 ; TOO LOW
CAILE A2,132
JRST OPF7 ; TOO HIGH
CAIL A2,100 ; LOWER CASE ALPHA?
SUBI A2,40 ; YES - RECODE TO UPPER CASE ALPHA
POPJ SP,0
OPF7: MOVEI A2,0
POPJ SP,0
LIT
PRGEND
TITLE CLOSEFILE - CLOSEFILE ROUTINE
; PROCEDURE CLOSEFILE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(425,CLOSEFILE)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPL A1,.N(DL) ; GET ARGUMENT
CAIL A1,40 ; 0 <= N < 40?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,CLFILE ; YES - CLOSE RELEVANT FILE
JRST .EXIT(DL)
LIT
PRGEND
TITLE TRANSFILE - TRANSFER FILE ROUTINE
; PROCEDURE TRANSFILE;
.EXIT=1
SEARCH ALGPRM,ALGSYS
LIBENT(426,TRANSFILE)
XWD 0,1
XWD $PRO!$N!$SIM,1
PUSHJ SP,XFILE ; TRANSFER FILE
JRST .EXIT(DL)
LIT
PRGEND
TITLE BACKSPACE - MAGNETIC TAPE BACKSPACE ROUTINE
; PROCEDURE BACKSPACE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(427,BACKSPACE)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPL A1,.N(DL) ; GET CHANNEL NUMBER
CAIL A1,20 ; 0 <= N < 20?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,BSPACE
JRST .EXIT(DL)
LIT
PRGEND
TITLE ENDFILE - MAGNETIC TAPE ENDFILE ROUTINE
; PROCEDURE ENDFILE(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(430,ENDFILE)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPL A1,.N(DL) ; GET CHANNEL NUMBER
CAIL A1,20 ; 0 <= N < 20?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,ENFILE
JRST .EXIT(DL)
LIT
PRGEND
TITLE REWIND - MAGNETIC TAPE REWIND ROUTINE
; PROCEDURE REWIND(N); VALUE N; INTEGER N;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(431,REWIND)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPL A1,.N(DL) ; GET CHANNEL NUMBER
CAIL A1,20 ; 0 <= N < 20?
IOERR 14,(A1) ; NO - COMPLAIN
PUSHJ SP,REWND.
JRST .EXIT(DL)
LIT
PRGEND
TITLE IOCHAN - INPUT/OUTPUT CHANNEL STATUS ROUTINE
; BOOLEAN PROCEDURE IOCHAN(N); VALUE N; INTEGER N;
.EXIT=1
.N=3
SEARCH ALGPRM,ALGSYS
LIBENT(432,IOCHAN)
XWD 0,3
XWD $PRO!$B!$SIM,2
XWD $VAR!$I!$FOV,.N
EDIT(036); ALLOW IOCHAN TO REFERENCE DEFAULT TTY CHANNEL
AOSL A1,.N(DL) ; [E036] GET CHANNEL NUMBER + 1
CAILE A1,40 ; [E036] -1 <= N < 40?
IOERR 14,(A1) ; NO - COMPLAIN
ADDI A1,-1(DB) ; [E036] RELOCATE CHANNEL NUMBER
MOVE A0,%IODR(A1) ; GET CHANNEL ENTRY
HLRZM A0,.EXIT+1(DL) ; AND SET UP RESULT
JRST .EXIT(DL)
PRGEND
TITLE INFO - GENERAL INFORMATION ROUTINE
; INTEGER PROCEEDURE INFO(I); INTEGER I; VALUE I;
.EXIT=1
.I=3
SEARCH ALGPRM,ALGSYS
EXTERNAL .JBREL
LIBENT(441,INFO)
XWD 0,3
XWD $PRO!$I!$SIM,2
XWD $VAR!$I!$FOV,.I
SETO A2, ; PRESET ANSWER
MOVE A1,.I(DL) ; GET FUNCTION REQUIRED
CAIL A1,0 ; SENSIBLE ?
CAIL A1,MAXINF
AOJA A2,INFO1 ; NO
XCT INFOTB(A1) ; DO IT
INFO1: MOVEM A2,.EXIT+1(DL) ; AND RETURN RESULT
JRST .EXIT(DL)
INFOTB: HRRZ A2,.JBREL ; 0 -CORE SIZE
DATE A2, ; 1 - DATE (15 BIT FORMAT)
TIMER A2, ; 2 - TIME (TICKS FROM MIDNIGHT)
MSTIME A2, ; 3 - TIME (MSEC FROM MIDNIGHT)
PUSHJ SP,INFRUN ; 4 - RUNTIME
SETZ A2, ; 5 - PROCESSOR
MOVE A2,%SYS20(DB) ; 6 - # OF STACK-SHIFTS
MOVE A2,%SYS23(DB) ; 7 - COMPILER VERSION WORD
MAXINF==.-INFOTB
INFRUN: PJOB A2,
RUNTIM A2,
POPJ SP,
PRGEND
TITLE FDATE/VDATE - STRING DATE ROUTINES
; STRING PROCEDURE FDATE/VDATE;
.EXIT=1
.LU=4
SEARCH ALGPRM,ALGSYS
EXTERNAL .JBREL
LIBENT(442,FDATE)
XWD 0,4
XWD $PRO!$SIM!$S,1
MOVEI A0,3 ; FLAG AS FDATE
JRST DATE0
LIBENT(443,VDATE)
XWD 0,4
XWD $PRO!$SIM!$S,1
MOVEI A0,77
DATE0: MOVEM A0,.LU(DL)
MOVEI A0,4
PUSHJ SP,GETCLR ; GET SPACE
HRLI A1,440700 ; MAKE BYTE-POINTER
MOVEM A1,.EXIT+1(DL) ; SET AS WORD 0 OF ANSWER
MOVEI A4,^D8 ; INITIALIZE COUNT
DATE A2, ; GET DATE
IDIVI A2,^D31 ; SPLIT OFF DAY
PUSH SP,A2 ; SAVE YEAR,MONTH
MOVEI A2,1(A3) ; GET GENUINE DAY
IDIVI A2,^D10
ADDI A2,"0" ; TO ASCII
CAIN A2,"0" ; IF 0
MOVEI A2," " ; SUPPRESS IT
IDPB A2,A1
ADDI A3,"0"
IDPB A3,A1
MOVEI A5,"-"
IDPB A5,A1
POP SP,A2 ; GET YEAR,MONTH
IDIVI A2,^D12 ; SPLIT THEM
LSH A3,1 ; GET MONTH * 2
ADD A3,[
POINT 7,MONTAB] ; GET POINTER TO ASCII MONTH
MOVE A0,.LU(DL) ; RECOVER # CHARS (3 OR MANY)
DATE2: ILDB A6,A3 ; GET CHARACTER OF MONTH
SOJL A0,DATE3 ; DONE IF FDATE & 3 CHARS DONE
JUMPE A6,DATE3 ; OR IF VDATE & ALL DONE
IDPB A6,A1
AOJA A4,DATE2 ; COUNT THE CHARACTERS
DATE3: IDPB A5,A1 ; "-"
ADDI A2,^D1964 ; GET REAL YEAR
DATE4: IDIVI A2,^D10
ADDI A3,"0"
PUSH SP,A3
JUMPN A2,DATE4
MOVEI A0,4
POP SP,A3
IDPB A3,A1
SOJG A0,.-2
MOVEM A4,.EXIT+2(DL) ; SET WORD 2 OF RESULT
JRST .EXIT(DL)
MONTAB:
ASCIZ/January/
ASCIZ/February/
ASCIZ/March/
ASCIZ/April/
ASCIZ/May/
0 ; THEY MUST ALL BE 2 WORDS LONG
ASCIZ/June/
0
ASCIZ/July/
0
ASCIZ/August/
ASCIZ/September/
ASCIZ/October/
ASCIZ/November/
ASCIZ/December/
PRGEND
TITLE TIME - GET TIME OF DAY STRING ROUTINE
; STRING PROCEDURE TIME;
.EXIT=1
SEARCH ALGPRM,ALGSYS
LIBENT(444,TIME)
XWD 0,3
XWD $PRO!$SIM!$S,1
MOVEI A0,2
PUSHJ SP,GETCLR ; GET SPACE FOR STRING
HRLI A1,440700 ; MAKE BYTE-POINTER TO IT
MOVEI A2,^D8
DMOVEM A1,.EXIT+1(DL) ; THE ANSWER (8 CHARS, DYNAMIC, RESULT-OF-PROC)
MSTIME A2, ; GET TIME OF DAY IN MILLISECONDS
ADDI A2,^D500 ; ROUND IT
IDIVI A2,^D1000 ; AND CONVERT TO SECONDS
MOVEI A4,":" ; SET SEPARATOR
IDIVI A2,^D60*^D60 ; GET HOURS
PUSHJ SP,TIME2 ; INSERT
IDIVI A2,^D60 ; GET MINUTES
PUSHJ SP,TIME1 ; INSERT
PUSHJ SP,TIME1 ; AND SECONDS
JRST .EXIT(DL) ; AND RETURN
TIME1: IDPB A4,A1 ; INSERT ":"
TIME2: PUSH SP,A3 ; SAVE A3 FOR LATER
IDIVI A2,^D10
ADDI A2,"0"
ADDI A3,"0"
IDPB A2,A1
IDPB A3,A1
POP SP,A2 ; OLD A3 TO A2
POPJ SP,
PRGEND
TITLE RAN / SETRAN / SAVRAN - RANDOM NUMBER GENERATOR
; INTEGER PROCEDURE RAN;
; PROCEDURE SETRAN(I); VALUE I; INTEGER I;
; INTEGER PROCEDURE SAVRAN;
.EXIT=1
.I=2
SEARCH ALGPRM,ALGSYS
LIBENT(445,RAN)
XWD 0,2
XWD $PRO!$SIM!$I,1
MOVE A0,[
4544503720] ; 14**29
MUL A0,%RAND(DB) ; LAST NUMBER
ASHC A0,4
LSH A1,-4
ADD A0,A1
TLZE A0,760000 ; IF OVERFLOW
ADDI A0,1 ; ADD 1
MOVEM A0,%RAND(DB)
MOVEM A0,.EXIT+1(DL) ; RETURN IT
JRST .EXIT(DL)
LIBENT(446,SETRAN)
XWD 0,2
XWD $PRO!$SIM!$N,2
XWD $VAR!$I!$FOV,.I
SKIPN A1,.I(DL) ; IF PARAM IS 0
MOVE A1,[
XWD 1,-1] ; THEN SET DEFAULT START
MOVEM A1,%RAND(DB)
JRST .EXIT(DL)
LIBENT(447,SAVRAN)
XWD 0,2
XWD $PRO!$SIM!$I,1
MOVE A1,%RAND(DB)
MOVEM A1,.EXIT+1(DL) ; RETURN LAST RANDOM NUMBER
JRST .EXIT(DL)
PRGEND
TITLE TRACEON /OFF - TURN ON/OFF DYNAMIC TRACE FLAG.
; PROCEDURE TRACEON;
; PROCEDURE TRACEOFF;
.EXIT=1
SEARCH ALGPRM,ALGSYS
EDIT(121); DECLARE %ALGDR AS AN EXTERNAL
EXTERN %ALGDR
LIBENT(455,TRACEON)
XWD 0,1
XWD $PRO!$N!$SIM,1
TLO DB,STMTST ; LIGHT BIT.
JRST .EXIT(DL)
LIBENT(456,TRACEOFF)
XWD 0,1
XWD $PRO!$N!$SIM,1
TLZ DB,STMTST
JRST .EXIT(DL)
PRGEND
TITLE PAUSE - DO AN EXIT 1,
; PROCEDURE PAUSE;
.EXIT=1
SEARCH ALGPRM,ALGSYS
LIBENT(461,PAUSE)
XWD 0,1
XWD $PRO!$N!$SIM,1
EXIT 1,
JRST .EXIT(DL)
PRGEND
TITLE DUMP - GET ALGDDT DUMP.
; PROCEDURE DUMP(N); VALUE(N); INTEGER(N); !N IS # OF BLOCKS TO DUMP. 0 = ALL;
.EXIT=1
.N=2
SEARCH ALGPRM,ALGSYS
LIBENT(462,DUMP)
XWD 0,2
XWD $PRO!$N!$SIM,2
XWD $VAR!$I!$FOV,.N
SKIPN A7,.N(DL)
MOVEI A7,777777 ; 'ALL'
PUSHJ SP,DDDUMP ; DO IT (TO CURRENT O/P CHANNEL)
JRST .EXIT(DL)
END