SYSTEMROUTINE READ(INTEGER TYPEBND,ADR) !*********************************************************************** !* THIS ROUTINE IS THE IMP IMPLICITLY SPECIFIED ROUTINE WITH A * !* %NAME PARAMETER. TYPEBND AND ADR ARE A 64 BIT DESCRIPTOR TO * !* THE ACTUAL PARAMETER. THE BND FIELD HAS THE TYPE CODE IN IT * !* (=1 FOR INTEGER =2 FOR REAL). FOR %SHORT %INTEGER, THE * !* PARAMETER WILL BE A STRING DESCRIPTOR OF LENGTH 2. * !* * !* THE METHOD USED IS SIMPLE REPEATED MULTIPLICATION USING LONG * !* REAL VARIABLES. SOME ROUNDING ERRORS ARE INTRODUCED WHICH * !* COULD BE AVOIDED BY USING PACKED DECIMAL INSTNS WITH NECESSARY* !* SCALING. * !*********************************************************************** INTEGER TYPE,PREC,FLAG,CURSYM; ! FLAG= 0FOR'-',1 FOR '+' INTEGER IVALUE,PARTYPE LONGINTEGER LIVALUE LONGLONGREAL RWORK,SCALE SWITCH RL(5:7) FLAG=1; TYPE=0 IF TYPEBND=X'58000002' THEN START PARTYPE = 1 PREC = 4 FINISH ELSE START PARTYPE = TYPEBND&7 PREC = (TYPEBND>>27)&7 FINISH IF TYPEBND=X'20000001' THEN TYPEBND = X'58000002' CURSYM = NEXT SYMBOL; ! CARE NOT TO READ TERMINATOR ! NOW IGNORE LEADING SPACES WHILE CURSYM=' ' OR CURSYM=NL CYCLE SKIP SYMBOL CURSYM=NEXT SYMBOL REPEAT IF CURSYM=X'19' THEN SIGNALEVENT 9,1 ! RECORD INITIAL MINUS IF CURSYM='-' THEN FLAG=0 AND CURSYM='+' ! MOVE OVER SIGN ONCE IT HAS ! BEEN RECORDED IN FLAG IF CURSYM='+' THEN START CYCLE SKIP SYMBOL CURSYM=NEXT SYMBOL REPEAT UNTIL CURSYM#' ' FINISH IF '0'<=CURSYM AND CURSYM<='9' THEN START RWORK=CURSYM-'0'; ! KEEP TOTAL IN RWORK TYPE=1; ! VALID DIGIT CYCLE SKIP SYMBOL CURSYM=NEXT SYMBOL EXIT UNLESS '0'<=CURSYM AND CURSYM<='9' RWORK=R'41A00000000000000000000000000000'*RWORK C +(CURSYM-'0');! CONTINUE EVALUATING REPEAT FINISH ELSE RWORK=0 IF CURSYM='.' AND PARTYPE=2 THEN START SCALE=R'41A00000000000000000000000000000' CYCLE SKIP SYMBOL CURSYM=NEXT SYMBOL EXIT UNLESS '0'<=CURSYM AND CURSYM<='9' TYPE=1 RWORK=RWORK+(CURSYM-'0')/SCALE SCALE=R'41A00000000000000000000000000000'*SCALE REPEAT FINISH ! ! THE VALUE HAS NOW BEEN READ INTO RWORK. THERE MIGHT BE AN EXPONENT ! E.G. '1.7@10 ' IS VALID DATA FOR READ ! IF (CURSYM='@' OR CURSYM='&') AND PARTYPE=2 THEN START IF TYPE=0 THEN TYPE=1 AND RWORK=1 SKIP SYMBOL; ! MOVE PAST THE '@' READ(X'29000001',ADDR(IVALUE));! RECURSIVE CALL TO FIND EXPONENT IF IVALUE=-99 THEN RWORK=0 ELSE C RWORK=RWORK*R'41A00000000000000000000000000000'**IVALUE FINISH SIGNALEVENT 4,1 IF TYPE=0; ! NO VALID DIGIT FOUND ! ! KNOCK NUMBER INTO RIGHT FORM ! IF PARTYPE=1 THEN START IF PREC = 6 THEN START LIVALUE = LINT(RWORK) IF FLAG=0 THEN LIVALUE = - LIVALUE *LSD_LIVALUE *ST_(TYPEBND) RETURN FINISH IVALUE= INT(RWORK) IF FLAG=0 THEN IVALUE=-IVALUE ! If %HALF %INTEGERs were signed, we would have to include ! the following code to recognise 'capacity exceeded': ! %IF PREC=4 %THEN %START ! %IF X'0001FFFF'#IVALUE>>15#0 %THEN %START ! ! Force 'capacity exceeded': ! IVALUE = IVALUE ! X'FFFF0000' ! %FINISH %ELSE %START ! ! Avoid 'capacity exceeded' if it's negative: ! IVALUE = IVALUE & X'0000FFFF' ! %FINISH ! %FINISH ! *LSS_IVALUE *ST_(TYPEBND) RETURN FINISH IF PARTYPE#2 THEN PSYSMES (X'80000000',338) IF FLAG=0 THEN RWORK=-RWORK IF PREC<5 THEN PREC = 5 -> RL(PREC) RL(5): ! 32 BIT REAL *LSD_=X'7F'; *USH_=25 *OR_=1; *USH_=31; ! ACC=X'7F00000080000000' *AND_RWORK; *RAD_RWORK; ! SOFTWARE ROUND *STUH_(TYPEBND) RETURN RL(6): ! 64 BIT REAL *LSD_=X'7F'; *USH_=56; *AND_RWORK *SLSD_=1; *USH_=55; *AND_RWORK+8 *LUH_TOS ; *RAD_RWORK; ! SOFTWARE ROUND *STUH_(TYPEBND) RETURN RL(7): ! 128 BIT REAL *LSQ_RWORK *ST_(TYPEBND) ! ! %MONITOR (N) == FORCE FAULT NO N ! N=16 REAL INSTEAD OF INTEGER IN DATA ! N=14 SYMBOL IN DATA ! END ! %CONSTLONGREAL IMAX=2147483647; ! MAX INTEGER FOR 32 BIT WORD ! NEEDS CHANGING FOR OTHER WLENGT CONSTLONGREAL DZ=0 SYSTEMLONGREALFN FRACPT(LONGREAL X) !*********************************************************************** !* RETURNS (X-INTPT(X)) AS THE RESULT * !*********************************************************************** RESULT =X-INTPT(X) END ROUTINESPEC PRINTFL(LONGREAL X,INTEGER N) SYSTEMROUTINE PRINT(LONGREAL X,INTEGER N,M) !*********************************************************************** !* PRINTS A REAL NUMBER (X) ALLOWING N PLACES BEFORE THE DECIMAL * !* POINT AND M PLACES AFTER.IT REQUIRES (M+N+2) PRINT PLACES * !* UNLESS (M=0) WHEN (N+1) PLACES ARE REQUIRED. * !* * !* A LITTLE CARE IS NEEDED TO AVOID UNNECESSARY LOSS OF ACCURACY * !* AND TO AVOID OVERFLOW WHEN DEALING WITH VERY LARGE NUMBERS * !*********************************************************************** LONGREAL ROUND LONGLONGREAL Y,Z STRING (127)S INTEGER I,J,L,SIGN,SPTR M=M&63; ! DEAL WITH STUPID PARAMS IF N<0 THEN N=1 ELSE START IF N>31 THEN START SPACES (N-31) N = 31 FINISH FINISH X=X+DZ; ! NORMALISE SIGN=' '; ! '+' IMPLIED IF X<0 THEN SIGN='-' Y=MOD(X); ! ALL WORK DONE WITH Y IF Y>1@15 OR N=0 THEN START ; ! MEANINGLESS FIGURES GENERATED IF N>M THEN M=N; ! FOR FIXED POINT PRINTING PRINT FL(X,M); ! OF ENORMOUS NUMBERS RETURN ; ! SO PRINT IN FLOATING FORM FINISH IF M<=20 THEN ROUND=1/(2*TENPOWERS(M)) ELSE C ROUND= 0.5/R'41A00000000000000000000000000000'**M;! ROUNDING FACTOR Y=Y+ROUND ->FASTPATH IF N+M<=16 AND Y<TENPOWERS(N) I=0;Z=1 CYCLE ; ! COUNT LEADING PLACES I=I+1;Z=10*Z; ! NO DANGER OF OVERFLOW HERE REPEAT UNTIL Z>Y SPTR=1 WHILE SPTR<=N-I CYCLE CHARNO(S,SPTR)=' ' SPTR=SPTR+1 REPEAT CHARNO(S,SPTR)=SIGN SPTR=SPTR+1 J=I-1; Z=R'41A00000000000000000000000000000'**J CYCLE CYCLE L=INT PT(Y/Z); ! OBTAIN NEXT DIGIT Y=Y-L*Z;Z=Z/10; ! AND REDUCE TOTAL CHARNO(S,SPTR)=L+'0' SPTR=SPTR+1 J=J-1 REPEAT UNTIL J<0 IF M=0 THEN EXIT ; ! NO DECIMAL PART TO BE O/P CHARNO(S,SPTR)='.' SPTR=SPTR+1 J=M-1; Z=R'41A00000000000000000000000000000'**(J-1) M=0 Y=10*Y*Z REPEAT LENGTH(S)=SPTR-1 -> OPUT FASTPATH: ! USE SUPK WITHOUT SCALING L=M+N+2; ! NO OF BYTES TO BE OPUT IF M=0 THEN L=L-1 Y=Y*TENPOWERS(M); ! CONVERT TO INTEGER J=N-1 I=30-M-N; ! FOR DECIMAL SHIFT *LSQ_Y *FIX_B *MYB_4 *ISH_B *CDEC_0 *LD_S *LB_L *MVL_L =1; ! LENGTH INTO STRING *DSH_I *CPB_B ; ! SET CC=0 FOR SUPK *LDB_J *JAT_11,6; ! TILL SUPK FIXED! *SUPK_L =DR ,0,32; ! UNPACK WITH LEADING SPACES *JCC_7,<DESSTACKED> *STD_TOS ; ! FOR SIGN INSERTION DESSTACKED: *LDB_2 *SUPK_L =1,0,32 *SUPK_L =1,0,48; ! FORCE ZERO BEFORE DP *SLD_TOS *LB_SIGN *STB_(DR ); ! INSERT SIGN *LB_46; ! ISO DECIMAL POINT *LD_TOS *LDB_M *JAT_11,<NOFRPART>; ! INTEGER PRINTING *STB_(DR ) *INCA_1 *SUPK_L =DR ,0,48; ! ZEROFILL NOFRPART: *LDB_(S) *INCA_1 *ANDS_L =DR ,0,63; ! FORCE ISO ZONE CODES OPUT: J=IOCP(15,ADDR(S)) END ; ! OF ROUTINE PRINT !8 SYSTEMROUTINE WRITE(INTEGER VALUE,PLACES) STRING (16)S INTEGER D0,D1,D2,D3,L IF PLACES>14 THEN START SPACES (PLACES-14) PLACES = 14 FINISH *LSS_VALUE; *CDEC_0 ! Acc is now 64 bits, holding the value as a packed decimal ! number, i.e. 15 decimal digits coded in binary in 4 bits ! each, followed by a 'sign' quartet at the least significant ! end. The largest possible absolute value would be 2**31 ! which is 2,147,483,648. Hence at least the first five ! quartets must be zero. *LD_S; *INCA_1; *STD_TOS ! *LD_S gets a byte vector descriptor to the whole of S - ! the bound will be 17 and the address will point to the ! 'length byte'. So DR (and TOS) now point to the text ! field of the IMP string. *CPB_B ; ! SET CC=0 *SUPK_L =15,0,32; ! UNPACK & SPACE FILL ! Acc is now zero except for the sign quartet which is ! unchanged at the least significant end. The first ! 15 text bytes of S now have the value in unpacked ! decimal format (unsigned). CC will be zero if the ! value is zero, and non-zero otherwise. The unpacked ! decimal string in S will have no leading zeros: leading ! bytes will be X'20' (ISO space) - but the digits will ! be in EBCDIC form, i.e. X'Fn'. If the number is zero, ! then all fifteen bytes will be spaces. If it is not, then ! a descriptor will have been planted on TOS which points ! to the byte immediately preceding the first digit (i.e., ! to the last of the leading spaces). ! ! D2 will get a (zero length) descriptor to the byte immediately ! after the fifteenth digit - i.e., to the last byte of S. *STD_D2; *JCC_8,<WASZERO> ! ! If the value was not zero - ! copy the descriptor-to-last-leading-space into D0: *LD_TOS ; *STD_D0; ! FOR SIGN INSERTION ! restore the descriptor to the first byte of text: *LD_TOS ! convert digits to ISO: ! (this uses the MASK to clear the top two bits of each byte, ! thus leaving the spaces - X'20' - unchanged, but coverting ! EBCDIC digits X'Fn' to their ISO equivalents X'3n'.) *MVL_L =15,63,0; ! FORCE ISO ZONE CODES IF VALUE<0 THEN BYTEINTEGER(D1)='-'; ! D0 is a descriptor ! to the appropriate place for a sign, and D1 is the ! address word of that descriptor. L=D3-D1; ! L is the number of bytes occupied by significant ! digits with a leading space or sign. OUT: IF PLACES>=L THEN L=PLACES+1 ! D3=D3-L-1 ! BYTEINTEGER(D3)=L ! D3=IOCP(15,D3) ! Since we know the characters are all valid, we can use IOCP ! entry point 19 to avoid the checking involved in IOCP 15 ! (which is PRINT STRING, i.e. simulating repeated PRINT ! SYMBOLs). D3 = D3 - L D2 = L ! D2, D3 are a descriptor to the stuff to be printed. IOCP ! does not mind that the TYPE fields are zero. D3 = IOCP (19,ADDR(D2)) RETURN WASZERO: BYTEINTEGER(D3-1)='0' L=2; -> OUT END ; !OF WRITE !* SYSTEMROUTINE PRINTFL(LONGREAL XX,INTEGER N) !*********************************************************************** !* PRINTS IN FLOATING POINT FORMAT WITH N PLACES AFTER THE * !* DECIMAL POINT. ALWAYS TAKES N+7 PRINTING POSITIONS. * !* CARE REQUIRED TO AVOID OVERFLOW WITH LARGE X * !*********************************************************************** STRING (47)S LONGLONGREAL ROUND,FACTOR,LB,UB,X,Y INTEGER COUNT,INC,SIGN,L,J N=N&31 IF N<=20 THEN Y=TENPOWERS(N) ELSE C Y=TENPOWERS(20)*TENPOWERS(N-20) ROUND=R'41100000000000000000000000000000'/(2*Y) LB=1-ROUND; UB=10-ROUND SIGN=' ' X=XX+DZ; ! NORMALISE IF X=0 THEN COUNT=-99 ELSE START IF X<0 THEN X=-X AND SIGN='-' INC=1; COUNT=0 FACTOR=R'4019999999999999999999999999999A' IF X<=1 THEN FACTOR=10 AND INC=-1 ! FORCE INTO RANGE 1->10 WHILE X<LB OR X>=UB CYCLE X=X*FACTOR; COUNT=COUNT+INC REPEAT FINISH X=X+ROUND IF N>16 THEN START ; ! TOO BIG FOR CDEC WITHOUT SCALING LENGTH(S)=N+4 CHARNO(S,1)=SIGN L=INTPT(X) CHARNO(S,2)=L+'0' CHARNO(S,3)='.' J=1 WHILE J<=N CYCLE X=(X-L)*10 L=INTPT(X) CHARNO(S,J+3)=L+'0' J=J+1 REPEAT FINISH ELSE START X=X*Y J=30-N *LSQ_X *FIX_B *MYB_4 *ISH_B ; ! NOCHECKING NEEDED AS N LIMITED *CDEC_0; ! GIVES 128 BIT DECIMAL N0 *LB_N *ADB_4 *LD_S *MVL_L =1; ! LENGTH INTO STRING *DSH_J *LB_SIGN *MVL_L =1; ! SIGN INTO STRING *SUPK_L =1,0,48; ! FIRST DIGIT INTO STRING *MVL_L =1,0,46; ! DOT INTO STRING *LDB_N *SUPK_L =DR ,0,48; ! UNPACK FR PT &ZEROFILL *LDB_(S) *INCA_1 *ANDS_L =DR ,0,63; ! FORCE ISO ZONE CODES FINISH CHARNO(S,N+4)='@' J=IOCP(15,ADDR(S)) WRITE(COUNT,2) END ; ! OF ROUTINE PRINTFL