/MATH.PA FOR OS78 V4 /ORIGINALLY: /6 MATH: STRING ARITHMETIC FOR BASIC V7A / / / / / / / / / /COPYRIGHT (C) 1978, 1979, 1981 BY DIGITAL EQUIPMENT CORPORATION / / / / / / / / / / /THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT NOTICE /AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT /CORPORATION. DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY /FOR ANY ERRORS THAT MAY APPEAR IN THIS DOCUMENT. / /THE SOFTWARE DESCRIBED IN THIS DOCUMENT IS FURNISHED TO THE PURCHASER /UNDER A LICENSE FOR USE ON A SINGLE COMPUTER SYSTEM AND CAN BE COPIED /(WITH INCLUSION OF DIGITAL'S COPYRIGHT NOTICE) ONLY FOR USE IN SUCH /SYSTEM, EXCEPT AS MAY OTHERWISE BE PROVIDED IN WRITING BY DIGITAL. / /DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR THE USE /OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY /DIGITAL. / / / / / / / / / / /MATH: STRING ARITHMETIC FOR OS/8 AND OS/78 BASIC VERSON= "B PATCH= 0 /EDIT HISTORY: /28-DEC-77 CREATION / 7-MAR-78 CLEAN LISTING UP, FIX BUG IN PRINT USING /PROVIDES STRING ADDITION, SUBTRACTION, MULTIPLICATION, /DIVISION, INTEGER, AND "PRINT USING" CAPABILITIES. /INPUT: /A AND B ARE INPUT STRINGS, ONE 7-BIT CHAR PER WORD, /TERMINATED BY 0 WORD. ONLY LEGAL CHARS ARE /MINUS SIGNS, PLUS SIGNS, SPACES, TABS, /NUMERIC DIGITS, ONE PERIOD. TOTAL LENGTH OF A /OR B MUST NOT EXCEED "MAX" NUMERIC DIGITS; ANY /ADDITIONAL DIGITS ARE IGNORED. /OUTPUT: /SAC CONTAINS RESULT, ONE 7-BIT CHAR PER WORD, /WITH LEADING SPACE OR MINUS SIGN FOLLOWED BY /DIGITS AND UP TO ONE DECIMAL POINT (PERIOD). /LEADING AND/OR TRAILING ZEROS ARE SUPPRESSED. /TRUNCATION IS DONE WHEN RESULT WOULD HAVE /EXCEEDED "MAX" SIGNIFICANT DIGITS. /THE LENGTH OF THE SAC IS RETURNED TO BRTS /IN THE AC. /GLOBAL SYMBOLS IN BRTS ERROR= 1400 SACLIM= 120 GOBACK= 4400 /BASE ADDRESS FOR STRING ARITHMETIC PACKAGE STPACK= 2000 FIELD 1 /SET THE FIELD NOW /PAGE 0 DEFINITIONS *100 TMP1, 0 TMP2, 0 TMP3, 0 TMP4, 0 TMP5, 0 TMP6, 0 TMP7, 0 TMP8, 0 TMP9, 0 TMP10, 0 PA, 0 PB, 0 LC, 0 CARRY, 0 B1, 0 B2, 0 B3, 0 B4, 0 A1, 0 A2, 0 A3, 0 A4, 0 A5, 0 /NOTE: THE FOLLOWING 6 WORDS /MUST BE CONTIGUOUS. SA, 0 LA, 0 RA, 0 SB, 0 LB, 0 RB, 0 FMTPTR, 0 USOPTR, 0 USOCTR, 0 SPECFG, 0 /THE FOLLOWING SYMBOL DEFINES THE MAXIMUM NUMBER OF /SIGNIFICANT DIGITS SUPPORTED MAX= 17 /=15 DECIMAL. /THE FOLLOWING SWITCH ADAPTS THE "PRINT USING" /STATEMENT FOR EUROPEAN STANDARD NOTATION. EUROPE= 0 /SET TO 1 TO INTERCHANGE /PERIOD AND COMMA. /INSTRUCTIONS THAT GENERATE CONSTANTS AC0001= CLA IAC AC0002= CLA CLL CML RTL AC2000= CLA CLL CML RTR AC3777= CLA CLL CMA RAR AC4000= CLA CLL CML RAR AC5777= CLA CLL CMA RTR AC7775= CLA CLL CMA RTL AC7776= CLA CLL CMA RAL /CHARACTER DEFINITIONS PERIOD= ".&177 MINUS= "-&177 PLUS= "+&177 SPACE= " &177 TAB= 211&177 ZERO= "0&177 STAR= "*&177 DOLLAR= "$&177 HASH= "#&177 AMPER= "&&177 COMMA= ",&177 IFNZRO EUROPE < COMMA= ".&177 PERIOD= ",&177> /GENERAL TERMINATOR END= 0 *STPACK /STRING ARITHMETIC ENTRY POINTS ADD, JMS MATH /SAC = A + B 0 / OPERATION CODE SUB, JMS MATH /SAC = A - B 1 INVSUB, JMS MATH /SAC = B - A 1001 MUL, JMS MATH /SAC = A * B 4000 DIV, JMS MATH /SAC = A / B 6000 INVDIV, JMS MATH /SAC = B / A 7000 /INITIALIZATION CODE: /CLEAR VARIABLES AND INTERMEDIATE REGISTER (C, /INTERCHANGE POINTERS TO A AND B IF "INVERSE" FUNCTION, /COMPRESS DIGITS IN BOTH A AND B, TEST DIGITS, /CONVERT DIGITS TO BCD, GET SIGNS, COUNT DIGITS /TO LEFT AND TO RIGHT OF DECIMAL POINT, /SAVE SIGN OF RESULT, DISPATCH TO PROPER ROUTINE. MATH, 0 JMS CLEAR /CLEAR VARIABLES. SA / LOCATION OF 1ST VARIABLE. -6 / -NUMBER TO CLEAR. JMS CLEAR /CLEAR INTERNAL RESULT ARRAY C / LOCATION OF ARRAY. -MAX-MAX / -LENGTH. TAD I MATH /GET OPERATION TYPE. RTL /IS IT INVERSE FUNCTION? SPA CLA JMP MA1 TAD (A /NO; SETUP POINTERS TO A AND B NORMALLY. DCA PA TAD (B DCA PB JMP MA2 MA1, TAD (B /YES; SETUP POINTERS IN REVERSE ORDER. DCA PA TAD (A DCA PB MA2, JMS SCAN /SCAN AND COMPRESS A. PA;SA JMS SCAN /SCAN AND COMPRESS B. PB;SB TAD SA /ADD SIGNS TOGETHER IN ORDER TO XOR THEM TAD SB TAD I MATH /ADD IN OPERATION TYPE. SMA /IS OPERATION MUL/DIV? JMP MA3 /NO, MUST BE ADD/SUB. DCA SA /YES, XOR OF SA AND SB IS SIGN OF RESULT. TAD I MATH /GET OPERATION TYPE. /DISPATCH ON OPERATION, MUL OR DIV. RAL SMA CLA JMP I (MULOP JMP I (DIVOP MA3, RAR /XOR OF SA AND SB TO LINK TO SELECT /ACTUAL ADDITION OR SUBTRACTION /(LINK=1 FOR SUBTRACTION. /(NOTE: INITIAL SIGN OF RESULT /IS ALREADY IN SA. SZL CLA /AC=ARGUMENT FOR "JMS ADSB". TAD (SBS-ADS /SBS: SUBTRACTION. TAD (ADS /ADS: ADDITION. JMP I (ADDSUB /SUBROUTINE TO CLEAR AN ARRAY CLEAR, 0 TAD I CLEAR /ADDRESS. ISZ CLEAR DCA TMP1 TAD I CLEAR /-LENGTH. ISZ CLEAR DCA TMP2 CL1, DCA I TMP1 ISZ TMP1 ISZ TMP2 JMP CL1 JMP I CLEAR /SUBROUTINE TO SCAN AND COMPRESS INPUT ARRAYS SCAN, 0 TAD I SCAN ISZ SCAN DCA TMP1 /ADDRESS OF POINTER. TAD I TMP1 /ADDRESS OF ARRAY. DCA TMP1 /TMP1=START OF ARRAY (INPUT). TAD TMP1 DCA TMP2 /TMP2=START OF ARRAY (OUTPUT). TAD I SCAN ISZ SCAN DCA TMP3 /TMP3=ADDR OF (SIGN;LEFT;RIGHT. STA /INITIALIZE ONCE-ONLY SWITCHES. DCA TMP4 STA DCA TMP5 DCA TMP6 TAD (-MAX-1 /INITIALIZE MAXIMUM CHECKER. DCA TMP7 SCLOOP, TAD I TMP1 /GET NEXT CHAR. JMS I (BRANCH /HANDLE SPECIAL CHARACTERS. SCDONE /END OF STRING. -MINUS; SC2 -PERIOD; SC1 -SPACE; IGNORE -PLUS; IGNORE -TAB; IGNORE END JMP I (SC4 /MUST BE A DIGIT. SCDONE, JMP I SCAN PAGE SC4, ISZ TMP4 /MUST BE A DIGIT: /POINT TO LA OR LB (FIRST TIME ONLY). JMP SC3 ISZ TMP3 SC3, ISZ TMP7 /TEST FOR OVER "MAX" DIGITS. SKP /OK. JMP I (SCDONE /TOO MANY DIGITS: TRUNCATE AND RETURN. ISZ I TMP3 /COUNT LA,LB,RA,RB. ISZ TMP6 /CHAR CAME. TAD I TMP1 /ACCEPT AND COMPRESS THE CHAR. TAD (-60 /TEST DIGIT FOR LEGALITY: LEGAL DIGITS SPA CLA /ARE BETWEEN 060 AND 071 ASCII. JMP DI-1 /ERROR: ILLEGAL CHARACTER IN NUMBER. TAD I TMP1 TAD (-72 SMA CLA JMP DI-1 /ERROR: ILLEGAL CHARACTER IN NUMBER. TAD I TMP1 ISZ TMP1 TAD (-60 /CONVERT TO BINARY CODED DECIMAL (BCD). DCA I TMP2 ISZ TMP2 JMP I (SCLOOP /HANDLE DECIMAL POINT SC1, ISZ TMP5 /ONCE ONLY, JMP DP-1 /ERROR: MORE THAN 1 DEC. POINT. ISZ TMP6 /CHAR CAME. ISZ TMP3 /POINT TO RA OR RB. JMP IGNORE /OTHERWISE IGNORE IT. /HANDLE MINUS SIGN SC2, TAD TMP6 /HAS A DIGIT OR PERIOD COME YET? SZA CLA JMP DM-1 /YES: ERROR. ISZ I TMP3 /NO: SET SIGN TO 1. /FALL THROUGH TO IGNORE IT. /IGNORE THE CHAR IGNORE, ISZ TMP1 JMP I (SCLOOP /ILLEGAL CHARACTER ERROR CIF 0 /CALL FIELD 0 ERROR ROUTINE. DI, JMS I (ERROR /ERROR: ILLEGAL CHARACTER IN NUMBER. JMP IGNORE /IGNORE IT AND CONTINUE. /ERROR: MORE THAN 1 DEC. POINT. CIF 0 /CALL FIELD 0 ERROR ROUTINE. DP, JMS I (ERROR /ERROR: MORE THAN 1 DEC. POINT. JMP IGNORE /IGNORE IT AND CONTINUE. /ILLEGAL MINUS SIGN ERROR CIF 0 /CALL FIELD 0 ERROR ROUTINE. DM, JMS I (ERROR /ERROR: MINUS SIGN AFTER DIGIT OR POINT. JMP IGNORE /IGNORE IT AND CONTINUE. /ADDITION/SUBTRACTION OPERATION /NOTE: C THROUGH C+MAX-1 WILL CONTAIN THE INTEGER PORTION, /C+MAX THROUGH C+MAX+MAX-1 WILL CONTAIN THE DECIMAL PORTION. ADDSUB, DCA AD11 /INITIALIZE ADD OR SUB OPERATION. TAD PA /TRANSFER A TO C. DCA TMP1 TAD LA /SHIFT TO PROPER PLACE IN C. CIA TAD (C+MAX) DCA TMP2 TAD LA /TMP3=LENGTH OF A. TAD RA CMA DCA TMP3 AD1, ISZ TMP3 /END OF A YET? SKP JMP AD2 /YES: ADD B TO C. TAD I TMP1 /NO: TRANSFER THE CHAR. ISZ TMP1 DCA I TMP2 ISZ TMP2 JMP AD1 /ADD B TO C OR SUBTRACT B FROM C AD2, TAD LB /CALCULATE LENGTH OF B. TAD RB CMA DCA B3 /B3=B WIDTH. TAD B3 CMA TAD PB DCA B2 /B2=B POINTER. TAD RB /ADD/SUB INTO PROPER PLACE IN C. TAD (C+MAX DCA B1 /B1=C POINTER. TAD B1 CIA TAD (C-1 DCA B4 /B4=C WIDTH. JMS I (ADSB /ADD OR SUBTRACT. AD11, 0 / ADS OR SBS FOR ADD OR SUBTRACT. TAD CARRY /ANY FINAL CARRY OR BORROW? SNA CLA JMP I (ADTRAN /NO: TRANSFER C TO SAC. TAD AD11 /OVERFLOW FROM LEFT-MOST DIGIT: MEANING /DEPENDS ON OPERATION. TAD (-ADS /IS IT ADDITION? SZA CLA JMP TENCMP /SUBTRACTION: OVERFLOW INDICATES /LARGER FROM SMALLER. DO 10'S COM- /PLEMENT OF RESULT. /OVERFLOW ERROR CIF 0 /CALL FIELD 0 ERROR ROUTINE. OV, JMS I (ERROR /ERROR: NUMBER TOO BIG TO REPRESENT /(NUMERIC OVERFLOW ON ADDITION, /MULTIPLICATION, DIVISION). JMP I (ZEROUT /RETURN 0. /ATTEMPTED SUBTRACTION OF A LARGER NUMBER FROM A /SMALLER: DO 10'S COMPLEMENT OF RESULT TENCMP, ISZ SA /COMPLEMENT SIGN OF RESULT. TAD (-MAX-MAX DCA TMP1 /TMP1=LENGTH OF C. STA DCA TMP2 /TMP2=ONCE-ONLY SWITCH. TAD (C+MAX+MAX /START AT RIGHT END OF C. DCA TMP3 /TMP3=POINTER INTO C. TC1, STA /GET PREVIOUS DIGIT OF C. TAD TMP3 DCA TMP3 TAD I TMP3 SZA /IS DIGIT 0? JMP TC2 AC0001 /YES: HAS A NON-ZERO DIGIT BEEN SEEN? TAD TMP2 SNA CLA JMP TC3 /NO: IGNORE DIGIT. /YES: FALL THROUGH TO CMPL. IT. TC2, ISZ TMP2 /IS THIS FIRST NON-ZERO DIGIT? IAC /NO: 9'S COMPLEMENT IT. CIA /YES: 10'S COMPLEMENT IT. TAD (12 DCA I TMP3 TC3, ISZ TMP1 /MORE DIGITS IN C TO COMPLEMENT? JMP TC1 /YES: COMPLEMENT NEXT DIGIT. JMP I (ADTRAN /NO: TRANSFER C TO SAC. PAGE /TRANSFER C TO SAC (ADDITION AND SUBTRACTION) ADTRAN, TAD (-MAX-1 DCA TMP5 /TMP5=LOCATION OF DECIMAL POINT. MLTRAN, /ENTRY POINT TO TRANSFER C TO SAC /FOR MULTIPLICATION AND DIVISION. TAD (C DCA TMP1 /TMP1=POINTER INTO C. TAD (SAC DCA TMP2 /TMP2=POINTER INTO SAC. DCA TMP3 /TMP3=ZERO SUPPRESSION SWITCH. TAD (-MAX DCA TMP4 /TMP4=OUTPUT SIGNIFICANCE LIMIT. TAD (-MAX-MAX DCA TMP6 /TMP6=INPUT SIGNIFICANCE LIMIT. JMS SGNOUT /STORE SIGN. ADOUT, ISZ TMP5 /SCAN NEXT DIGIT OF C. /IS DECIMAL POINT DUE? JMP AD5 /NOT YET. TAD (PERIOD /YES, OUTPUT IT. DCA I TMP2 ISZ TMP2 ISZ TMP3 /TURN OFF ZERO SUPPRESSION FOLLOWING /DECIMAL POINT. AD5, TAD I TMP1 /GET THE DIGIT OF C. ISZ TMP1 SZA /DO ZERO SUPPRESSION: /IS THE DIGIT ZERO? JMP AD4 /NO: TURN OFF ZERO SUPPRESSION AND /OUTPUT THE DIGIT. TAD TMP3 /IS ZERO SUPPRESSION ENABLED? SNA CLA JMP AD3 /YES: IGNORE THIS LEADING ZERO. /NO: FALL THROUGH TO OUTPUT THE /ZERO DIGIT. AD4, ISZ TMP3 /NON-ZERO DIGIT DETECTED: DISABLE /ZERO SUPPRESSION. TAD (ZERO /CONVERT BCD DIGIT TO ASCII CHARACTER. DCA I TMP2 /OUTPUT THE CHAR. ISZ TMP2 ISZ TMP4 /HAVE "MAX" DIGITS BEEN OUTPUT YET? JMP AD3 /NOT YET. AC0001 /YES: TEST FOR OVERFLOW. TAD TMP5 SPA CLA JMP I (OV-1 /DECIMAL POINT STILL TO THE RIGHT. /SAME OVERFLOW ERROR AS IN ADDITION. JMP AD6 /DELETE TRAILING ZEROS. AD3, ISZ TMP6 /MORE CHARS REMAINING IN C? JMP ADOUT /YES: PROCESS NEXT CHAR. AD6, TAD TMP5 /NO MORE CHARS IN C OR "MAX" CHARS OUTPUT: /DELETE TRAILING ZEROS. /GET PERIOD POSITION COUNTER TO FIND /OUT IF A DECIMAL POINT HAS BEEN /OUTPUT. SPA CLA /TMP5 WILL BE >=0 IF SO. JMP ADEND /NO DECIMAL: SKIP TRAILING ZERO /SUPPRESSION. AD7, STA /DECIMAL: DELETE TRAILING ZEROS. /LOCATE PREVIOUS CHAR. TAD TMP2 DCA TMP2 TAD I TMP2 /GET THE CHAR. TAD (-ZERO /IS IT ZERO? SNA JMP AD7 /YES: DELETE IT BY LOOPING. TAD (-PERIOD+ZERO /IF IT IS NON-ZERO, IS IT THE /DECIMAL POINT? SZA CLA ISZ TMP2 /NO: ALLOW THIS CHAR TO SURVIVE. ADEND, JMP FINISH /YES: DELETE USELESS DECIMAL POINT. /FINISH UP. /STORE SIGN IN SAC SGNOUT, 0 TAD SA /SIGN OF RESULT. RAR /LINK=SIGN. SNL CLA JMP I SGNOUT /POSITIVE: NO SIGN. TAD (MINUS /NEGATIVE: STORE MINUS SIGN. DCA I TMP2 ISZ TMP2 /COUNT THE CHAR. JMP I SGNOUT /RETURN. /MULTIPLICATION OPERATION /DO ENTIRE MULTIPLICATION IN DOUBLE PRECISION INTO /RESULT REGISTER C THEN TRANSFER C TO SAC. MULOP, /INITIALIZE POINTERS. TAD PA /LOCATE RIGHT END OF A. TAD LA TAD RA DCA TMP1 /TMP1=MAJOR POINTER INTO A. TAD (C+MAX+MAX DCA TMP2 /TMP2=MAJOR POINTER INTO C. TAD PB /LOCATE RIGHT END OF B. TAD LB TAD RB DCA TMP3 /TMP3=RIGHT END OF B. TAD LB TAD RB CMA DCA TMP4 /TMP4=LENGTH LIMIT OF B. TAD LA TAD RA CMA DCA TMP5 /TMP5=LENGTH LIMIT OF A. MLLOOP, ISZ TMP5 /FINISHED MULTIPLYING BY A? JMP I (MUL1 /NO. TAD RA /YES: TRANSFER RESULT WITH DECIMAL /POINT AT RA+RB FROM RIGHT /(2*MAX-RA-RB FROM LEFT). TAD RB TAD (-MAX-MAX-1 DCA TMP5 /TMP5=LOCATION OF DECIMAL POINT. JMP MLTRAN /TRANSFER C TO SAC, SAME AS FOR /ADDITION/SUBTRACTION. /FINISH UP: CHECK FOR NULL SAC, CALCULATE SAC LENGTH, /RETURN TO BRTS IN FIELD 0. FINISH, TAD I (SAC /IF 1ST CHAR OF SAC IS "-", TAD (-MINUS / SUBTRACT 1 FROM SAC LENGTH SNA CLA / AND SEE IF RESULT IS 0 STA / (MEANS NO NUMBER WAS OUTPUT). TAD TMP2 /CURRENT POINTER. TAD (-SAC /CALCULATE LENGTH OF NUMBER. SNA CLA JMP ZEROUT /NULL SAC: RETURN "0". TAD TMP2 /NON-NULL SAC: CALCULATE /SAC LENGTH. /TMP2=SAC OUTPUT POINTER TAD (-SAC /CALCULATE LENGTH CIA /NEGATE IT JMP DONE /RETURN IT TO BRTS. /RETURN "0" TO BRTS IN FIELD 0. ZEROUT, TAD (ZERO DCA I (SAC STA /LENGTH=1. DONE, CIF CDF 0 JMP I (GOBACK PAGE /MULTIPLY B BY NEXT DIGIT OF A. MUL1, STA TAD TMP1 DCA TMP1 TAD I TMP1 /GET CURRENT DIGIT IN A. CLL RTL /MULTIPLY BY 12 TO GET ROW IN TABLE. TAD I TMP1 CLL RAL TAD (MTAB DCA TMP6 /TMP6=ADDRESS OF ROW IN TABLE. TAD TMP2 DCA TMP7 /TMP7=POINTER TO OFFSET IN C. TAD TMP3 DCA TMP8 /TMP8=POINTER INTO B. TAD TMP4 DCA TMP9 /TMP9=LENGTH LIMIT OF B. DCA CARRY /NO INITIAL CARRY. MLSTEP, ISZ TMP9 /DONE MULTIPLYING ALL OF B? JMP MUL4 /NO. MUL7, STA /YES: PROPAGATE ANY FINAL CARRY. /GET NEXT C DIGIT. TAD TMP7 DCA TMP7 TAD CARRY SNA JMP MUL5 /NO MORE CARRY. TAD I TMP7 /ADD CARRY INTO NEXT C DIGIT. TAD (-12 /CHECK FOR DIGIT OVERFLOW. SPA JMP MUL6 /NO OVERFLOW. DCA I TMP7 /OVERFLOW: STORE LOW ORDER DIGIT. AC0001 /CARRY=1. DCA CARRY JMP MUL7 MUL6, TAD (12 /RESTORE DIGIT DCA I TMP7 /STORE DIGIT IN C. MUL5, STA /OFFSET C BY 1. TAD TMP2 DCA TMP2 JMP I (MLLOOP /CONTINUE WITH NEXT DIGIT OF A. /INNER MULTIPLICATION LOOP: MULTIPLY TWO DIGITS, /ADD TO PARTIAL PRODUCT IN C MUL4, STA /GET NEXT B DIGIT. TAD TMP8 DCA TMP8 STA /LOCATE C DIGIT. TAD TMP7 DCA TMP7 TAD TMP6 /ROW ADDRESS FOR A DIGIT. TAD I TMP8 /ADD IN B DIGIT TO SELECT TABLE ENTRY /FOR A*B. DCA TMP10 TAD I TMP10 /GET PRODUCT DIGITS. AND (17 /GET LOW ORDER DIGIT. TAD I TMP7 /ADD INTO C. TAD CARRY /ADD CARRY FROM LAST PRODUCT. TAD (-24 /CHECK FOR DIGIT OVERFLOW. /NOTE: GREATEST VALUE OF THE SUM /IS 26 DECIMAL (32 OCTAL). SPA JMP MUL8 /SUM IS < 20 DECIMAL. DCA I TMP7 /20 OR OVER: STORE LOW ORDER DIGIT. TAD (40 /=2 IN THE HIGH ORDER POSITION, /REPRESENTING THE CARRY. JMP MUL3 MUL8, TAD (12 /TEST FOR 10 TO 19. SPA JMP MUL2 DCA I TMP7 /10 TO 19: STORE LOW ORDER DIGIT. TAD (20 /=1 IN THE HIGH ORDER POSITION. JMP MUL3 MUL2, TAD (12 /DIGIT IS 0-9: RESTORE DIGIT. DCA I TMP7 /STORE IT IN C. MUL3, TAD I TMP10 /GET PRODUCT DIGITS AGAIN, /ADDING IN ANY CURRENT CARRY. RTR /GET HIGH ORDER DIGIT. RTR AND (17 DCA CARRY /SAVE AS NEXT CARRY. JMP MLSTEP /MULTIPLY BY NEXT DIGIT IN B. /ENTRY POINT FOR INTEGER OPERATION /COPIES THE INTEGER PORTION OF THE NUMBER STORED IN ARRAY /A TO SAC. NO ERROR CHECKING IS DONE. INTEGR, TAD (A /INITIALIZE. DCA TMP1 /TMP1=POINTER TO INPUT ARRAY. TAD (SAC DCA TMP2 /TMP2=POINTER TO SAC. TAD (-MAX-3 DCA TMP3 /TMP3=SAC LIMIT COUNTER. IN1, TAD I TMP1 /GET NEXT INPUT DIGIT. SNA /END OF STRING YET? JMP IN2 /YES. TAD (-PERIOD /IS IT A DECIMAL POINT? SNA CLA JMP IN2 /YES. TAD I TMP1 /OTHER CHAR: COPY INTACT. ISZ TMP1 DCA I TMP2 ISZ TMP2 ISZ TMP3 /TOO MANY CHARACTERS? JMP IN1 /NO, LOOP. IN2, JMP I (FINISH /YES: END OF INTEGER PART HAS /BEEN REACHED. CALCULATE LENGTH OF SAC /AND RETURN. /SUBROUTINE TO BRANCH TO ROUTINES. BRANCH, 0 SNA JMP BR2 /END OF STRING. DCA BRTEMP BR1, ISZ BRANCH TAD I BRANCH ISZ BRANCH SNA JMP I BRANCH /NO MATCH (END=0). TAD BRTEMP /EQUALS AC? SZA CLA JMP BR1 /NO: CONTINUE. BR2, TAD I BRANCH /YES: JUMP TO ROUTINE. DCA BRTEMP JMP I BRTEMP BRTEMP, 0 PAGE /DIVISION OPERATION DIVOP, JMS I (CLEAR /CLEAR REMAINDER (IN SAC). SAC / ADDRESS. -MAX-MAX / -LENGTH. DV1, TAD LB /TEST FOR NULL DIVISOR. TAD RB SZA CLA JMP DV3 /DIVISION BY ZERO ERROR NOP /PAD TO MAKE DIFFERENT FROM "RE" ERROR CIF 0 /CALL FIELD 0 ERROR ROUTINE. DV, JMS I (ERROR /ERROR: ATTEMPTED DIVISION BY 0. JMP I (ZEROUT DV3, TAD I PB /DELETE LEADING ZEROS FROM DIVISOR /IN ORDER TO AVOID LENGTHY DIVIDE LOOPS. SZA CLA JMP DV2 /NO (MORE) LEADING ZERO DIGITS. STA /DELETE LEADING ZERO. TAD LB DCA LB ISZ PB /POINT PAST THE DELETED DIGIT. JMP DV1 DV2, TAD PA /TRANSFER A TO SAC. DCA TMP1 TAD (SAC DCA TMP2 TAD LA TAD RA CMA DCA TMP3 JMP DV6 DV7, TAD I TMP1 ISZ TMP1 DCA I TMP2 ISZ TMP2 DV6, ISZ TMP3 JMP DV7 TAD LB /CALCULATE DEC PT POSITION IN QUOTIENT. CIA TAD LA IAC /LC = LA - LB + 1 DCA LC TAD LC /IF LC<0, DECREASE REQUIRED DIVISION /STEPS (LOSS OF PRECISION). SMA JMP DV4 CIA /DECREASE LOOP COUNT. JMP DV5 DV4, TAD (-MAX-1 /IF LC >= 0, TEST FOR OVERFLOW. /(IS LC > MAX?) SMA CLA JMP I (OV-1 /OVERFLOW: DECLARE ERROR, RETURN 0. DV5, TAD (-MAX-2 /NO OVERFLOW: SET UP DIVIDE LOOP COUNT. DCA TMP1 /TMP1=DIVIDE LOOP COUNT. TAD TMP1 /CALCULATE OFFSET INTO C FOR FIRST /QUOTIENT DIGIT. TAD (C+MAX+2 DCA TMP2 /TMP2=OFFSET INTO C. TAD LB /CALCULATE RIGHT END OF B. TAD RB TAD PB DCA B2 /B2=ADDR OF RIGHT END OF B. TAD B2 CMA TAD PB DCA B3 /B3=B WIDTH. TAD B3 CMA TAD (SAC DCA B1 /B1=RIGHT END OF SAC. TAD B3 /INITIAL SAC WIDTH SAME AS B. DCA B4 /MAIN DIVISION LOOP: DO TRIAL SUBTRACTION DVLOOP, ISZ TMP1 /HAVE "MAX" DIGITS BEEN DIVIDED OUT? JMP DVSTEP /NOT YET. TAD LC /YES: TRANSFER RESULT WITH DECIMAL /POINT AT LC FROM LEFT (0 IF LC<0). SPA CLA CMA DCA TMP5 JMP I (MLTRAN /TRANSFER C TO SAC, SAME AS FOR /MULTIPLICATION. /TRIAL SUBTRACTION DVSTEP, JMS ADSB /SAC = SAC - B. SBS / SUBTRACT. TAD CARRY /ANY FINAL BORROW? SZA CLA JMP DV12 /YES. ISZ I TMP2 /NO FINAL BORROW: TRIAL SUBTRACTION /SUCCEEDED. INCREMENT QUOTIENT (C) DIGIT. JMP DVSTEP /DO NEXT TRIAL SUBTRACTION. /FINAL BORROW: TRIAL SUBTRACTION FAILED. DV12, JMS ADSB /RESTORE SAC: SAC = SAC + B. ADS / ADDITION. ISZ TMP2 /POINT TO NEXT DIGIT IN /QUOTIENT (C). ISZ B1 /POINT TO NEXT DIGIT IN REMAINDER /(SAC) FOR TRIAL SUBTRACTIONS. STA /INCREASE LENGTH OF REMAINDER. TAD B4 DCA B4 JMP DVLOOP /DONE THIS DIVISION STEP. MORE TO GO? /SUBROUTINE TO ADD/SUBTRACT STRINGS /INPUT: / B1 = 1+ADDR OF RIGHT END OF C / B2 = 1+ADDR OF RIGHT END OF B / B3 = -(1+LENGTH OF B) / B4 = -(1+LENGTH OF C) /CALL: / JMS ADSB /C=C+B OR C=C-B / ADS OR SBS /ADD OR SUBTRACT /OUTPUT: / CARRY = FINAL CARRY OR BORROW ADSB, 0 TAD I ADSB /GET ARGUMENT. ISZ ADSB DCA A1 /A1=ADS OR SBS. TAD B1 DCA A2 /A2=POINTER TO C. TAD B2 DCA A3 /A3=POINTER TO B. TAD B3 DCA A4 /A4=COUNTER FOR B. TAD B4 DCA A5 /A5=COUNTER FOR C. ADSB1, DCA CARRY /OR BORROW. ISZ A5 /MORE DIGITS IN SUM REGISTER (C)? SKP JMP I ADSB /NO; RETURN. NOTE: CARRY=FINAL CARRY. STA /YES: POINT TO NEXT DIGIT OF C. TAD A2 DCA A2 ISZ A4 /IN CARRY/BORROW ZONE (AFTER ALL B /DIGITS HAVE BEEN ADDED/SUBTRACTED)? JMP I (ADSB2 /NOT YET. TAD CARRY /YES: ANY CARRY/BORROW? SNA CLA JMP I ADSB /NONE; RETURN. STA /RIPPLE A CARRY OR BORROW. /STAY IN CARRY/BORROW ZONE. DCA A4 JMP I (ADSB3 /SKIP ADDING IN B. PAGE ADSB2, STA /GET NEXT DIGIT OF B. TAD A3 DCA A3 TAD I A3 ADSB3, TAD CARRY /ADD IN PREVIOUS CARRY OR BORROW. JMP I A1 /GO TO "ADS" TO ADD, "SBS" TO SUBTRACT. /ADDITION STEP ADS, TAD I A2 /ADD C DIGIT. TAD (-12 /CARRY? SPA JMP ADSB4 /NO. DCA I A2 /YES: STORE LOW ORDER DIGIT. IAC /SET CARRY. JMP I (ADSB1 /LOOP FOR NEXT DIGIT. ADSB4, TAD (12 /NO CARRY: RESTORE DIGIT. DCA I A2 /STORE DIGIT. JMP I (ADSB1 /LOOP FOR NEXT DIGIT. /SUBTRACTION STEP SBS, CIA /NEGATE B+BORROW OR BORROW. TAD I A2 /SUBTRACT FROM C DIGIT. SPA /BORROW? JMP ADSB5 /YES. DCA I A2 /NO: STORE DIGIT. JMP I (ADSB1 /LOOP FOR NEXT DIGIT. ADSB5, TAD (12 /STORE 10'S COMPLEMENT OF DIGIT. DCA I A2 IAC /SET BORROW. JMP I (ADSB1 /LOOP FOR NEXT DIGIT. /"PRINT USING" STATEMENT USING, STA /SET "ONCE ONLY" FLAG TO INDICATE /WHEN A (#&-*.$) CHAR IS FOUND. DCA SPECFG TAD (SAC /INITIALIZE OUTPUT POINTER. DCA USOPTR TAD (-SACLIM DCA USOCTR /INIT FOR MAX OUTPUT CHARS. TAD I (UINIT /TEST INITIALIZATION FLAG. SNA CLA JMP USLOOP /PRINT ANOTHER VALUE. TAD (FMTBUF /INITIALIZE FORMAT STRING POINTER. DCA FMTPTR USLOOP, TAD I FMTPTR /LOOK FOR NUMERIC SPECIFICATION /IN THE FORMAT STRING. JMS I (BRANCH /RECOGNIZE CHAR. EOFMT /END OF STRING. -HASH; NUMSPC -AMPER; NUMSPC -MINUS; NUMSPC -STAR; NUMSPC -PERIOD;NUMSPC -DOLLAR;NUMSPC END TAD I FMTPTR /UNRECOGNIZED FORMAT CHAR: /COPY INTACT TO OUTPUT. ISZ FMTPTR JMS I (UOUT /OUTPUT CHAR. JMP USLOOP /END OF FORMAT STRING DETECTED EOFMT, TAD (FMTBUF /RE INITIALIZE FORMAT STRING POINTER. DCA FMTPTR /FALL THROUGH /FINISH UP "PRINT USING": RETURN TO BRTS IN FIELD 0 UDONE, TAD USOPTR DCA TMP2 JMP I (FINISH /BEGINNING OF NUMERIC SPECIFICATION DETECTED NUMSPC, TAD SPECFG /IS THIS THE START OF THE FOLLOWING /NUMERIC SPECIFICATION, OR THIS ONE? SNA CLA JMP UDONE /FOLLOWING: RETURN TO BRTS. DCA SPECFG /THIS ONE: REMEMBER AND PROCESS. TAD (B DCA PB DCA SB /CLEAR VARIABLES. DCA LB DCA RB JMS I (SCAN /SCAN AND COMPRESS CURRENT /INPUT VALUE (B). PB;SB TAD FMTPTR /INITIALIZE FIRST SCAN OF FORMAT. DCA TMP1 /TMP1=POINTER TO FORMAT. DCA TMP2 /TMP2=DOLLAR SWITCH. DCA TMP3 /TMP3=STAR SWITCH. DCA TMP4 /TMP4=LEFT DIGITS. DPSCAN, TAD I TMP1 /FIRST SCAN OF FORMAT. /SCAN UP TO DEC. PT. TO COUNT /NUMERIC FORMAT CHARS. JMS I (BRANCH DOLEFT /END OF STRING: DO OUTPUT SCAN. -HASH; UCOUNT -AMPER; UCOUNT -MINUS; MINCOM -STAR; GOTSTR -COMMA; MINCOM -DOLLAR;GOTDLR END JMP I (DOLEFT /UNRECOGNIZED CHAR: 2ND SCAN. GOTSTR, ISZ TMP3 /SET STAR SEEN SWITCH UCOUNT, ISZ TMP4 /TALLY CHAR MINCOM, ISZ TMP1 /BUMP FORMAT PTR JMP DPSCAN /SCAN FOR MORE GOTDLR, ISZ TMP2 /SET DOLLAR SWITCH JMP MINCOM /BUMP FORMAT PTR AND LOOP PAGE /HANDLE CHARS TO LEFT OF DP DOLEFT, DCA TMP7 /ENABLE LEADING ZERO SUPPRESSION. /TMP7=ZERO SUPPRESS SWITCH. LFTSCN, TAD I FMTPTR /OUTPUT SCAN OF FORMAT /(UP TO DEC. PT.). JMS I (BRANCH US50 /END OF STRING. -HASH; US12 -AMPER; US13 -MINUS; US14 -STAR; US13 -PERIOD;GOTDP -COMMA; US17 -DOLLAR;US30 END US50, JMS I (UCLEAN /UNRECOGNIZED CHAR. /OUTPUT ANY EXTRA DIGITS. JMP I (USLOOP /LOOK FOR NEXT NUMBER. US12, ISZ TMP7 /#: STOP LEADING ZERO SUPPRESSION. US13, TAD TMP4 /&*: ANY LEADING ZERO? CIA TAD LB SMA CLA JMP US20 /NO: OUTPUT DIGIT. ISZ LB /YES: COUNT A ZERO DIGIT. TAD TMP7 /IS ZERO SUPPRESSION ENABLED? SZA CLA JMP US31 /NO: OUTPUT "0". US15, TAD TMP3 /STAR (*) MODE? SNA CLA TAD (SPACE-STAR /NO: OUTPUT SPACE. TAD (STAR /YES: OUTPUT STAR. LFTOUT, JMS I (UOUT /OUTPUT CHAR. US30, ISZ FMTPTR /NEXT FORMAT CHAR. JMP LFTSCN /CONTINUE OUTPUT SCAN. US31, JMS UDOLL /OUTPUT $ IF REQUIRED. TAD (ZERO /OUTPUT "0". JMP LFTOUT UDOLL, 0 TAD TMP2 /ANY DOLLAR PENDING? SNA CLA JMP I UDOLL /NO. DCA TMP2 /YES. CANCEL IT AND TAD (DOLLAR /OUTPUT "$". JMS I (UOUT /OUTPUT CHAR. JMP I UDOLL US14, TAD SB /MINUS SIGN (-). SZA CLA TAD (MINUS-SPACE TAD (SPACE JMP LFTOUT /OUTPUT - OR SPACE. US17, TAD TMP7 /COMMA (,). /ZERO SUPPRESS ENABLED? SNA CLA JMP US15 /YES: OUTPUT SPACE/STAR. TAD (COMMA /NO: OUTPUT COMMA. JMP LFTOUT US20, JMS UDOLL /CHECK FOR DOLLAR. ISZ TMP7 /DISABLE LEADING ZERO SUPPRESS. JMS I (UDOUT /OUTPUT DIGIT. JMP US30 /NEXT FORMAT CHAR. GOTDP, JMS UDOLL /OUTPUT $ IF REQUIRED. JMS I (UCLEAN /OUTPUT EXTRA DIGITS. TAD (PERIOD /OUTPUT DEC. PT. JMS I (UOUT /OUTPUT CHAR. RGTSCN, ISZ FMTPTR /NEXT FORMAT CHAR. TAD I FMTPTR /OUTPUT SCAN, DECIMAL PART. JMS I (BRANCH USLOOP /END OF STRING. -HASH; ZERFIL -AMPER; BLKFIL -STAR; STRFIL -MINUS; MINFIL END JMP I (USLOOP /UNRECOGNIZED CHAR. ZERFIL, JMS RZFILL /# ZERO BLKFIL, JMS RZFILL /& SPACE STRFIL, JMS RZFILL /* STAR MINFIL, TAD SB /- SZA CLA TAD (MINUS-SPACE TAD (SPACE RGTOUT, JMS I (UOUT /OUTPUT CHAR. JMP RGTSCN /CONTINUE SCAN. RZFILL, 0 STA /IS THIS A TRAILING ZERO? TAD RB SPA JMP DOFILL DCA RB /NO: OUTPUT THE DIGIT. JMS I (UDOUT /OUTPUT DIGIT. JMP RGTSCN /CONTINUE THE SCAN. DOFILL, CLA /YES: OUTPUT SPECIAL CHAR. TAD I RZFILL JMP RGTOUT PAGE /PRINT USING CLEAN UP. OUTPUT ANY REMAINING DIGITS UCLEAN, 0 TAD LB CMA TAD TMP4 DCA TMP4 SKP JMS UDOUT /OUTPUT DIGIT. ISZ TMP4 /DONE? JMP .-2 /NO. JMP I UCLEAN /YES. UOUT, 0 /OUTPUT A CHAR. DCA I USOPTR ISZ USOPTR ISZ USOCTR /SAC FILLED UP? JMP I UOUT /NO. JMP I (UDONE /YES. UDOUT, 0 /OUTPUT NEXT DIGIT. TAD I PB /GET DIGIT. ISZ PB TAD (ZERO /CONVERT FROM BCD TO ASCII. JMS UOUT /OUTPUT IT. JMP I UDOUT /MULTIPLY TABLE /THIS TABLE IS USED TO MULTIPLY TWO DIGITS /TOGETHER, AS FOLLOWS: /PRODUCT = TABLE ENTRY (DIGIT1 + (12 * DIGIT2) ) /THIS METHOD IS FASTER THAN BITWISE MULTIPLICATION /OF THE TWO DIGITS. /PRODUCT FORMAT: 000 0HH HHL LLL /H = HIGH ORDER PRODUCT BCD DIGIT /L = LOW ORDER PRODUCT BCD DIGIT /CREATED WITH FOLLOWING TECO MACRO: / ^O0U212<0U112-DI / $%2U2>^D MTAB, 0;0;0;0;0;0;0;0;0;0 0;1;2;3;4;5;6;7;10;11 0;2;4;6;10;20;22;24;26;30 0;3;6;11;22;25;30;41;44;47 0;4;10;22;26;40;44;50;62;66 0;5;20;25;40;45;60;65;100;105 0;6;22;30;44;60;66;102;110;124 0;7;24;41;50;65;102;111;126;143 0;10;26;44;62;100;110;126;144;162 0;11;30;47;66;105;124;143;162;201 PAGE /THE FOLLOWING FLAG IS SET NON-ZERO BY BRTS /TO INITIALIZE "PRINT USING" PROCESSING. UINIT, 0 /STRING NUMBER BUFFERS A, ZBLOCK MAX+3 B, ZBLOCK MAX+3 C, ZBLOCK MAX+MAX SAC, ZBLOCK MAX+MAX+1 /(USED TO BE 75) FMTBUF, ZBLOCK SACLIM+1 /BUFFER FOR PRINT USING FORMAT STRING /GLOBAL SYMBOLS IFNZRO UINIT-STPACK-2000 IFNZRO A-STPACK-2001 IFNZRO B-STPACK-2023 IFNZRO SAC-STPACK-2103 IFNZRO ADD-STPACK IFNZRO INTEGR-STPACK-707 IFNZRO USING-STPACK-1232 $