DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦17f7448eb⟧ TextFile

    Length: 86912 (0x15380)
    Types: TextFile
    Names: »D160«

Derivation

└─⟦ae2411776⟧ Bits:30008864 Diskette med tekster der formodes at være 31-D-152…161
    └─⟦this⟧ »D160« 

TextFile

****************************************** 
DMATHO.S 
created  770801;  last modified  791023 
****************************************** 
 
H ADD AND SUBTRACT 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOATING POINT REVERSE SUBTRACT ROUTINE 
;   NEGATE X AND ADD 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
RSUB    LD   A,(IX)     ; GET MS BYTE OF X 
        XOR  80H        ; NEGATE SIGN 
        LD   D,A        ; SAVE IT 
        LD   E,(IY)     ; GET MS BYTE OF Y 
        JP   AD05     
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOATING POINT SUBTRACT ROUTINE 
;   NEGATE Y AND ADD 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
SUB     LD   A,(IY)     ; GET MSBYTE OF Y 
        XOR  80H        ; NEGATE SIGN 
        LD   E,A        ; SAVE IT 
        LD   D,(IX)     ; GET MSBYTE OF X 
        JP   AD05         
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOATING POINT ADD ROUTINE 
; 
;   INPUT:  IX  PTS TO 1ST ARG 
;           IY  PTS TO 2ND ARG 
;   OUTPUT: IX  PTS TO SUM (X IS REPLACED BY SUM, Y IS UNCHANGED) 
;   ERRORS: EXPONENT OVERFLOW AND UNDERFLOW 
;   SPECIAL CASES: ZERO ARGUMENT(S) 
; 
;   INPUT FOR AD05: D CONTAINS MS BYTE OF X 
;                   E CONTAINS MS BYTE OF Y 
;   ALGORITHM:  ABSOLUTE VALUE MAGNITUDES ARE COMPARED, 
;       THE LARGER IS LOADED TO AC1, THE SMALLER TO AC2. 
;       AC2 IS SHIFTET TO ALIGN DECIMAL POINTS. 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
ADD     LD   D,(IX)     ; GET MS BYTES 
        LD   E,(IY)  
; 
; CHECK FOR ZERO ARGUMENTS 
; 
AD05    XOR  A          ; CLEAR A 
        CP   (IX+7) 
        JP   NZ,AD07    ; X IS NONZERO 
        CP   (IY+7) 
        RET  Z          ; Y IS ALSO ZERO 
        LD   A,E        ; GET Y MSBYTE 
        PUSH IY 
        POP  HL 
        CALL LD         ; COPY TO X 
        LD   (IX),A     ; STORE MSBYTE 
        RET 
 \f

AD07    LD   (IX),D     ; STRE NEW SIGN IN CASE Y IS 0 
        CP   (IY+7)      
        RET  Z          ; Y IS ZERO, RETURN X 
; 
; LOAD ARGUMENTS, LARGER MAGNITUDE IN AC1 
; 
        PUSH DE         ; SAVE MS BYTES 
        RES  7,D        ; CLEAR SIGN BITS 
        RES  7,E 
        CALL CP1        ; COMPARE X TO Y IGNORING SIGN 
        JR   C,AD10     ; X < Y 
        CALL STA1       ; X TO AC1 
        CALL STYA2      ; Y TO AC2 
        POP  BC         ; GET SIGNS 
        LD   A,B 
        XOR  C 
        LD   A,B        ; USE SIGN OF X FOR RESULT 
        JP   AD15 
AD10    CALL STYA1      ; Y TO AC1 
        CALL STA2       ; X TO AC2 
        POP  BC         ; GET SIGNS 
        LD   A,C 
        XOR  B 
        LD   A,C        ; USE SIGN OF Y FOR RESULT 
; 
; PRENORMALIZE BY SHIFTING AC2 RIGHT 
; 
AD15    EX   AF,AF'     ; SAVE RESULT SIGN, XOR FLAGS 
        LD   A,(AC1E)   ; GET AC1 EXPONENT 
        LD   HL,AC2E 
        SUB  (HL)       ; CALC SHIFT COUNT 
        JR   Z,AD30     ; FRACTIONS ALREADY ALIGNED 
        CP   13          
        JP   NC,FSTO    ; AC2 IS INSIGNIFICANT 
        LD   B,A        ; SET COUNTER 
AD20    XOR  A          ; CLEAR A 
        LD   HL,AC2     ; PT TO ACCUM 
        CALL SRD1       ; SHIFT RT 1 DIGIT 
        DJNZ AD20       ; COUNTER NOT 0 
; 
; INITIALIZE FOR ADD OR SUB 
; 
AD30    LD   B,7        ; COUNTER 
        LD   HL,AC20    ; POINTERS 
        LD   DE,AC10 
        AND  A          ; CLEAR CY 
        EX   AF,AF'     ; GET SIGN & FLAGS 
        JP   M,SB10     ; SIGNS WERE DIFFERENT 
; 
; ADD 
; 
        EX   AF,AF'     ; SAVE SIGN OF RESULT 
AD40    LD   A,(DE) 
        ADC  A,(HL) 
        DAA 
        LD   (DE),A 
        DEC  DE 
        DEC  HL 
        DJNZ AD40 
 \f

; 
; POST NORMALIZE, AT MOST 1 SHFT RIGHT 
; 
        LD   A,(AC1)    ; CHECK FOR OVERFLOW 
        AND  0F0H 
        JP   Z,FSTO     ; ALREADY NORMALIZED 
        LD   HL,AC1E 
        INC  (HL)       ; INCREMENT EXPONENT 
        JP   Z,OVERA    ; OVERFLOW 
        LD   HL,AC1     ; PT TO ACCUM 
        CALL SRD1       ; SHIFT RIGHT 
        JP   FSTO 
; 
; SUB 
; 
SB10    EX   AF,AF'     ; SAVE SIGN OF RESULT 
SB20    LD   A,(DE) 
        SBC  A,(HL) 
        DAA 
        LD   (DE),A 
        DEC  DE 
        DEC  HL 
        DJNZ SB20 
; 
; POST-NORMALIZE BY SHIFTING LEFT 
; 
        LD   A,(AC1E)   ; PUT EXP IN C 
        LD   C,A 
        LD   HL,AC1 
        CALL NORML2     ; NORMALIZE FRACTION 
        JP   Z,ZERO     ; ZERO FRACTION RESULT 
        JP   C,UNDER    ; EXPONENT UNDERFLOW 
        LD   A,C        ; STORE EXP 
        LD   (AC1E),A    
        JP   FSTO 
; 
; COPY AC1 TO (IX) AND SET SIGN OF RESULT 
; 
FSTO    LD   HL,AC1     ; PT TO AC1 
        CALL LD 
        JP   RSTO       ; SET SIGN FROM A' 
*H MULTIPLY 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOATING POINT MULTIPLY ROUTINE 
; 
;   INPUT:  IX  PTS TO MULTIPLICAND 
;           IY  PTS TO MULTIPLIER 
;   OUTPUT: IX  PTS TO PRODUCT (PRODUCT REPLACES X, Y IS UNCHANGED) 
;   ERRORS: EXPONENT OVERFLOW OR UNDERFLOW 
;   SPECIAL CASES:  ARGUMENT(S) ZERO 
;   ALGORITHM:  X, 2X, 4X, and 8X ARE STORED IN TEMPORARY REGS. 
;       Y IS PLACED IN AC1. 
;       MULTIPLIER IS EXAMINED BIT AT A TIME WITHIN EACH DIGIT, 
;       CORRESPONDING TEMP REGS ARE ADDED TO (IX), AND (IX) 
;       IS SHIFTED RIGHT. 
; 
;   TIMING:  APPROX 19814 (16916 IN LOOP) 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
 \f

;  
; CHECK FOR ZERO OPERANDS 
; 
MULT    XOR  A 
        CP   (IX+7) 
        JP   Z,ZERO 
        CP   (IY+7) 
        JP   Z,ZERO 
; 
; CALCULATE AND SAVE SIGN OF RESULT 
; 
        LD   A,(IX)     ; MS BYTE OF X 
        XOR  (IY) 
        EX   AF,AF'     ; SAVE IN A> 
; 
; STORE X, 2X, 4X, AND 8X IN TEMP REGISTERS 
; 
        PUSH IX 
        POP  DE 
        LD   HL,6 
        ADD  HL,DE 
        LD   (SAVE),HL  ; SAVE PTR TO LS BYTE 
        EX   DE,HL 
        CALL MDTL 
; 
; SAVE Y IN AC1 (IN CASE X AND Y ARE SAME) 
; CLEAR (IX) 
; 
        CALL STYA1      ; STORE Y IN AC1 
        LD   IY,AC1     ; PT TO Y 
        CALL ZERO       ; CLEAR X 
        LD   B,7        ; LOOP COUNTER 
        JP   ML20       ; SKIP SHIFT OF AC1 
; 
; SHIFT PRODUCT RIGHT ONE DIGIT 
; GET NEXT MULTIPLIER DIGIT 
; 
ML10    XOR  A          ; CLEAR A 
        CALL SRD        ; SHFT (IX) RIGHT 
        CALL MLDIG      ; MULTIPLY BY 2ND DIGIT 
        XOR  A 
        CALL SRD        ; SHFT (IX) RIGHT 
ML20    LD   C,(IY+6)   ; GET 2 DIGITS 
        DEC  IY         ; DECR PTR 
        CALL MLDIG      ; MULTIPLY BY 1ST DIGIT 
        DJNZ ML10       ; COUNTER NOT 0 
; 
; CHECK NORMALIZATION 
; 
        DEC  B          ; DEFAULT SHIFT COUNT IS -1 
        LD   A,(IX)     ; GET MS BYTE 
        AND  0F0H 
        JR   Z,ML60     ; ALREADY NORMALIZED 
        INC  B          ; SET SHIFT COUNT TO 0 
        XOR  A 
        CALL SRD        ; SHIFT 0 INTO (IX) 
 \f

; 
; CALCULATE EXPONENT OF RESULT 
; 
ML60    LD   A,(TEMPOE) ; EXP OF ORIGINAL X 
        SUB  80H        ; REMOVE BIAS 
        LD   C,A 
        LD   A,(IY+14)  ; EXP OF ORIGINAL Y 
        SUB  80H        ; REMOVE BIAS 
        ADD  A,C        ; ADD TWO EXPONENTS 
; 
; CHECK EXPONENT CALCULATION FOR ERRORS 
; 
MCHK    JP   PO,M10     ; NO OVERFLOW 
        ADD  A,B        ; ADD SHIFT COUNT 
        JP   PO,MERR    ; NO SECOND OVERFLOW 
        JP   M20 
M10     ADD  A,B        ; ADD SHIFT COUNT 
        JP   PE,MERR    ; OVERFLOW 
M20     ADD  A,80H      ; RESTORE BIAS 
        JP   Z,UNDER    ; UNDERFLOW 
        LD   (IX+7),A   ; STORE EXP 
        JP   RSTO 
*H DIVIDE 
; 
; RECIPROCAL 
; 
REC     CALL STO4       ; SAVE X 
        LD   HL,C1 
        CALL LD         ; GET A 1 
        LD   IY,TEMP4 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOATING POINT DIVISION ROUTINE 
; 
;   INPUT:  IX  PTS TO DIVIDEND 
;           IY  PTS TO DIVISOR 
;   OUTPUT: IX  PTS TO QUOTIENT (QUOT. REPLACES X, Y UNCHANGED) 
;   ERRORS: DIVISOR ZERO 
;           EXPONENT OVERFLOW OR UNDERFLOW 
;   SPECIAL CASES:  DIVIDEND ZERO 
;   ALGORITHM:  Y, 2Y,4Y,8Y ARE STORED IN TEMP. REGS. 
;       X IS PLACED IN AC1.  AC1 IS COMPARED TO THE TEMP 
;       REGS. A BIT AT A TIME WITHIN EACH DIGIT, SUBTRACTING 
;       WHEN TEMP <= AC1.  RESULT BITS ARE ACCUMULATED IN C, 
;       AND STORED A BYTE AT A TIME INTO (IX) 
;   TIMING:  APPROX. 22938 (20108 LOOP) 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; CHECK FOR ZERO OPERANDS 
; 
DIVI    XOR  A 
        CP   (IY+7) 
        JP   Z,DIVO     ; Y IS ZERO 
        CP   (IX+7) 
        JP   Z,ZERO     ; X IS ZERO 
; 
; CALCULATE AND SAVE SIGN OF RESULT 
; 
        LD   A,(IX)     ; MS BYTE OF X 
        XOR  (IY) 
        EX   AF,AF'     ; SAVE IN A> 
 \f

; 
; STORE Y, 2Y, 4Y, AND 8Y IN TEMP REGISTERS 
; 
        PUSH IY 
        POP  HL 
        CALL MDTL 
; 
; INITIALIZE AC1 
; 
        PUSH IX         ; SAVE IX 
        CALL STA1       ; STORE X IN AC1 
        LD   BC,701H    ; COUNTER IS 7, SHFT COUNT 1 
        PUSH BC         ; SAVE COUNTERS 
        LD   C,OFH      ; INIT C 
        LD   HL,TEMP0 
        CALL DVCP       ; COMPARE X TO Y (FRACTIONS) 
        JR   NC,DV30    ; X >= Y 
        POP  BC 
        DEC  C          ; DECR SHIFT COUNT 
        PUSH BC 
        JP   DV20       ; BEGIN WITH SHIFT DIGIT 
; 
; DIVIDE LOOP 
; 
DV10    PUSH BC         ; SAVE COUNTERS 
        LD   HL,AC1 
        XOR  A 
        CALL SLD1       ; SHIFT AC1 LEFT 1 DIGIT 
        CALL DVDIG      ; GET 1 DIGIT RESULT 
DV20    LD   HL,AC1 
        XOR  A 
        CALL SLD1       ; SHIFT AC1 LEFT A DIGIT 
DV30    CALL DVDIG      ; GET 2ND DIGIT RESULT 
        LD   A,C        ; COMPL RESULT IN A 
        CPL             ; TRUE RESULT 
        LD   (IX),A     ; STORE PAIR OF QUOTIENT DIGITS 
        INC  IX 
        POP  BC 
        DJNZ DV10       ; COUNTER NOT 0 
; 
; CALCULATE EXPONENT OF RESULT 
; 
        LD   B,C        ; PUT SHIFT COUNT IN B 
        LD   A,(TEMPOE) ; EXP OF ORIGINAL Y 
        SUB  80H 
        LD   C,A        ; SAVE UNBIASED EXP 
        LD   A,(AC1E)   ; EXP OF ORIGINAL X 
        SUB  80H        ; REMOVE BIAS 
        SUB  C          ; SUB TWO EXPONENTS 
        POP  IX         ; RESTORE IX 
        JP   MCHK       ; CHECK FOR ERRORS 
*H MULT, DIVI UTILITIES 
; 
; MLDIG  MULTIPLY DIGIT 
;   INPUT:  C   CONTAINS DIGIT IN LOW 4 BITS 
;           (SAVE) IS PTR TO LS BYTE OF ACCUM 
;   OUTPUT: C   IS ROTATED 4 BITS 
;           PRODUCT OF MPLICAND WITH DIGIT IS 
;           ADDED TO ACCUM 
;   TIMING 950 
; 
 \f

MLDIG   LD   HL,TEMP00  ; PT TO MPLICAND 
        RR   C 
        CALL C,MLADD    ; ADD X 
        LD   HL,TEMP10   
        RR   C 
        CALL C,MLADD    ; ADD 2X 
        LD   HL,TEMP20 
        RR   C 
        CALL C,MLADD    ; ADD 4X 
        LD   HL,TEMP30 
        RR   C 
        CALL C,MLADD    ; ADD 8X 
        RET 
; 
; MLADD   ADD UTILITY FOR MULTIPLY 
; 
;   INPUT:  HL  PTS TO NUMBER 
;           (SAVE) PTS TO LS BYTE OF ACCUM 
;   OUTPUT: 14 DIGIT NUMBER IS ADDED TO ACCUM 
;   TIMING 407 
; 
MLADD   LD   DE,(SAVE)  ; PT TO LS BYTE 
        AND  A          ; CLEAR CY 
        PUSH BC         ; SAVE BC 
        LD   B,7        ; SET COUNTER 
ML40    LD   A,(DE) 
        ADC  A,(HL) 
        DAA 
        LD   (DE),A 
        DEC  DE 
        DEC  HL 
        DJNZ ML40 
        POP  BC 
        RET 
; 
; RSTO  PRODUCES SIGN OF RESULT 
;   INPUT:  IX  PTS TO RESULT 
;           A'  BIT 7 IS SIGN BIT 
;   OUTPUT: IX  PTS TO RESULT 
;   TIMING 74 
; 
RSTO    LD   A,(IX)     ; GET MS BYTE 
        AND  0FH        ; CLEAR UPPER DIGIT 
        LD   B,A 
        EX   AF,AF'     ; GET NEW SIGN BIT 
        AND  80H 
        OR   B 
        LD   (IX),A     ; REPLACE MS BYTE 
        RET 
; 
; DVDIG  ROUTINE TO DIVIDE 1 DIGIT 
;   INPUT:  AC1 IS CURRENT REMAINDER (DIVIDEND) 
;           TEMP REGS CONTAIN 1,2,4,8*DIVISOR 
;   OUTPUT: C   CONTAINS QUOTIENT DIGIT IN LOW 4 BITS 
;               (C ROTATED LEFT) 
;           AC1 CONTAINS REMAINDER (< DIVISOR) 
;   TIMING 1162 
; 
 \f

DVDIG   LD   HL,TEMP3   ; PT TO 8Y 
        CALL DVCP 
        JR   C,DVD10    ; AC1 < 8Y 
        LD   HL,TEMP30 
        CALL DVSUB      ; 8Y <= AC1 
DVD10   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP2   ; PT TO 4Y 
        CALL DVCP 
        JR   C,DVD20    ; AC1 < 4Y 
        LD   HL,TEMP20 
        CALL DVSUB      ; 4Y < AC1 
DVD20   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP1   ; PT TO 2Y 
        CALL DVCP 
        JR   C,DVD30    ; AC1 < 2Y 
        LD   HL,TEMP10 
        CALL DVSUB      ; 2Y < AC1 
DVD30   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP0   ; PT TO Y 
        CALL DVCP       ; COMPARE TO AC1 
        JR   C,DVD40    ; AC1 < Y 
        LD   HL,TEMP00   
        CALL DVSUB      ; Y < AC1 
DVD40   RL   C          ; COMPL RESULT BIT IN C 
        RET 
; 
; DVCP  ROUTINE TO COMPARE (DE) TO AC1 
;   RETURNS CY SET IFF (DE) < AC1 
;   RETURNS Z  SET IFF (DE) = AC1 
;   TIMING APPROX 42 
; 
DVCP    LD   DE,AC1     ; PT TO AC1 
        LD   B,7        ; SET COUNTER 
DVC10   LD   A,(DE)     ; GET BYTE 
        CP   (HL) 
        RET  NZ         ; < OR > 
        INC  HL         ; INC PTRS 
        INC  DE 
        DJNZ DVC10      ; COUNTER NOT 0 
        RET 
;  
; DVSUB  ROUTINE TO SUBTRACT (DE) FROM AC1 
;   ASSUMES 14 DIGIT OPERANDS 
;   TIMING 376 
; 
DVSUB   LD   DE,AC10    ; PT TO ACCUM 
        AND  A          ; CLEAR CY 
        LD   B,7 
DV40    LD   A,(DE) 
        SBC  A,(HL) 
        DAA 
        LD   (DE),A 
        DEC  DE 
        DEC  HL 
        DJNZ DV40 
        RET 
; 
; ROUTINE TO LOAD TEMP REGISTERS 
;   TIMING 2014 
; 
 \f

MDTL    LD   DE,TEMP0   ; FIRST DEST 
        CALL MOV        ; LOAD TEMP0 
        LD   HL,TEMP0   ; PT TO SRC 
        RES  7,(HL)     ; CLEAR SIGN BIT 
        LD   B,3        ; SET COUNTER 
; 
; LOOP TO COPY TEMPN TO TEMPN+1 & SHFT LFT 1 BIT 
; 
MDTL1   LD   A,B        ; SAVE COUNTER 
        CALL MOV        ; MOVE TO NEXT TEMP 
        LD   B,A        ; RESTORE COUNTER 
        AND  A          ; CLEAR CY 
        CALL SLB1       ; SHFT LEFT (HL ALREADY OK) 
        INC  HL         ; PT TO MSBYTE JUST SHIFTED 
        DJNZ MDTL1      ; COUNTER NOT 0 
        RET 
; 
; DETERMINE OVER OR UNDER 
; 
MERR    JP   P,UNDER    ; UNDERFLOW 
        JP   OVERA 
; 
; DIVISION BY ZERO ERROR 
; 
DIV0    LD   HL,ERROR 
        SET  4,(HL) 
        JP   INF 
*H FIX 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FIX CONVERTS FLOATING POINT NUMBER TO 
;        16 BIT 2'S COMPLEMENT INTEGER 
;        (ROUNDING) 
; 
;   INPUT:  IX  PTS TO FL PT NUMBER 
;   OUTPUT: IX  PTS TO INTEGER 
;   ERRORS:  OVERFLOW IF X > 32767 OR X < -32768 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
FIX     LD   IY,C _5 
        CALL ADD         ; ADD .5 
        CALL FIXA        ; CONVERT NUMBER 
        JR   NC,FX10     ; NO OVERFLOW 
        LD   HL,ERROR 
        SET  6,(HL)      ; FLAG OVERFLOW 
        LD   HL,7FFFH    ; 32767 
        BIT  7,(IX) 
        JR   Z,FX10      ; POSITIVE SIGN 
        LD   HL,8000H    ; -32768 
FX10    LD   (IX),L      ; STORE INTEGER 
        LD   (IX+1),H 
        RET 
; 
; MAIN CONVERSION FOR FIX 
; 
;   RETURNS CY SET IF OVERFLOW 
;   RETURNS Z  SET IF EXACT INTEGER 
;   HL IS LOW 16 BITS OF INT(X) FOR ALL X < 10 13 
; 
 \f

FIXA    XOR  A 
        LD   H,A        ; CLEAR ACCUM 
        LD   L,A 
        LD   (SAVE),A   ; CLEAR FLAG 
; 
; CALCULATE   DIGITS LEFT AND RIGHT OF DECML PT 
; 
        LD   A,(IX+7)   ; GET EXP 
        SUB  80H        ; SUBTRACT BIAS 
        JR   C,FXA100   ; X < .1 
        JR   Z,FXA100   ; X < 1 
        LD   B,A        ; SAVE # LEFT DIGITS 
        LD   A,13 
        SUB  B 
        JR   C,FXA90    ; X >= 10 13 
        LD   C,A        ; SAVE   RIGHT DIGITS 
; 
; CONVERT LEFT DIGITS TO BINARY 
; 
        PUSH IX         ; SET POINTER 
        POP  IY 
        LD   A,(IY)     ; GET FIRST BYTE 
        INC  IY 
        JP   FXA20 
FXA10   CALL NZ,FXA110  ; OVERFLOW 
        LD   A,(IY)     ; GET NEXT TWO DIGITS 
        INC  IY 
        PUSH AF         ; SAVE THIS BYTE 
        RRA             ; GET LEFT DIGIT 
        RRA 
        RRA 
        RRA 
        CALL MAD        ; CONVERT LEFT DIGIT 
        DJNZ FXA15      ; COUNTER NOT 0 
        POP  AF         ; GET RIGHT DIGIT 
        AND  OFH 
        JR   FXA30 
FXA15   CALL NZ,FXA110  ; OVERFLOW 
        POP   AF        ; GET SAVED BYTE 
FXA20   CALL MAD        ; CONVERT RIGHT DIGIT 
        DJNZ FXA10      ; COUNTER NOT 0 
; 
; CALCULATE OR OF ALL DIGITS TO RIGHT OF DECML PT 
; 
        XOR  A          ; INITIALIZE A 
FXA30   LD   B,C        ; USE OTHER COUNTER 
        SRL  B          ; DIVIDE BY 2 
        JR   Z,FXA50    ; COUNT IS 0 
FXA40   OR   (IY)       ; OR 2 DIGITS 
        INC  IY 
        DJNZ FXA40      ; COUNTER NOT 0 
; 
; CONVERT TO 2'S COMPLEMENT 
; 
FXA50   BIT  7,(IX) 
        JR   Z,FXA80    ; POSITIVE SIGN 
        EX   DE,HL 
        LD   HL,0 
        AND  A 
        JR   Z,FXA60    ; EXACT INTEGER 
        INC  DE         ; CORRECT MAGNITUDE 
 \f

FXA60   SBC  HL,DE      ; SUBTRACT FROM 0 
        JP   P,FXA90    ; OVERFLOW 
FXA70   AND  A          ; SET Z OR NZ 
        LD   A,(SAVE)   ; GET FLAG 
        RLA             ; PUT IN CY 
        RET 
FXA80   BIT  7,H 
        JR   Z,FXA70    ; NO OVERFLOW 
FXA90   AND  A          ; SET Z OR NZ 
        SCF             ; SET CY 
        RET 
FXA100  LD   A,(IX+7)   ; A IS 0 IFF FRACTION 0 
        JP   FXA50 
FXA110  LD   A,(SAVE)   ; GET FLAG 
        OR   80H        ; TURN IT ON 
        LD   (SAVE),A 
        RET 
; 
; MAD ROUTINE TO MULTIPLY ACCUM BY 10 AND ADD NEW DIGIT 
; 
MAD     LD   D,H        ; SAVE COPY OF HL 
        LD   E,L 
        ADD  HL,HL      ; SHIFT LEFT 2 
        ADD  HL,HL 
        ADD  HL,DE      ; ADD COPY 
        ADD  HL,HL      ; SHIFT LEFT 1 
        AND  0FH        ; PUT NEW DIGIT IN DE 
        LD   E,A 
        LD   D,0 
        ADD  HL,DE      ; ADD NEW DIGIT 
        LD   A,H        ; TEST HIGH BITS 
        AND  0F0H 
        RET 
*H FLOAT 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FLOAT CONVERTS 16 BIT 2'S COMPLEMENT INTEGER TO 
;       FLOATING POINT FORMAT 
;   (FLOAT1 ASSUMES INPUT IS IN HL) 
; 
;   INPUT:  IX  PTS TO 16 BIT INTEGER 
;   OUTPUT: IX  PTS TO FLOATING PT NUMBER 
;   ERRORS: NONE 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; TEST INPUT 
; 
FLOAT   LD   L,(IX)     ; LOAD 16 BIT INTEGER 
        LD   H,(IX+1) 
FLOAT1  PUSH HL         ; SAVE INTEGER 
        CALL ZERO       ; CLEAR OUTPUT AREA 
        POP  HL 
        LD   A,H        ; TEST FOR ZERO 
        OR   L 
        RET  Z          ; INPUT WAS ZERO 
; 
; CONVERT TO SIGN MAGNITUDE, SIGN IN A' 
; 
        LD   A,H        ; GET SIGN BIT 
        AND  80H 
        JR   Z,FL10     ; POSITIVE 
 \f

        EX   DE,HL 
        LD   HL,0 
        SBC  HL,DE      ; NEGATE 
; 
; CONVERT BINARY TO DECIMAL 
; 
FL10    EX   AF,AF'     ; SAVE SIGN BIT 
        EX   DE,HL      ; SAVE ACCUM 
        PUSH IX 
        POP  HL         ; PT TO OUTPUT AREA 
        LD   BC,10000 
        CALL FLDIV      ; DIVIDE BY 10000 
        INC  HL         ; ADVANCE OUTPUT PTR 
        LD   BC,1000     
        CALL FLDIV      ; DIVIDE BY 1000 
        LD   BC,100 
        CALL FLDIV      ; DIVIDE BY 100 
        INC  HL         ; ADVANCE OUTPUT PTR 
        LD   BC,10 
        CALL FLDIV      ; DIVIDE BY 10 
        LD   A,E        ; GET REMAINDER 
        RLD             ; ROT INTO OUTPUT 
; 
; NORMALIZE RESULT, STORE SIGN 
; 
        LD   C,85H      ; EXPONENT 
        CALL NORML1      
        JP   RSTO       ; STORE SIGN 
; 
; ROUTINE TO DIVIDE DE BY BC 
;   4 BIT QUOTIENT IS ROTATED INTO (HL) 
; 
FLDIV   EX   DE,HL      ; PUT ACCUM IN HL 
        XOR  A          ; CLEAR A, CY 
        DEC  A          ; INITIALLY A IS -1 
FLDIV1  SBC  HL,BC      ; SUBTRACT DIVISOR 
        INC  A          ; INCR QUOTIENT 
        JR   NC,FLDIV1  ; RESULT NOT NEGATIVE 
        ADD  HL,BC      ; RESTORE REMAINDER 
        EX   DE,HL      ; SAVE ACCUM, GET PTR 
        RLD             ; STORE QUOTIENT 
        RET 
*H CP 
; 
; CP  FLOATING POINT COMPARE ROUTINE 
;    
;   RETURNS CY SET IF X < Y 
;   RETURNS Z  SET IF X = Y 
;   CP1 ASSUMES MS BYTES FOR X,Y IN D,E 
; 
CP      LD   D,(IX)     ; LOAD MS BYTES 
        LD   E,(IY) 
CP1     LD   A,D        ; GET SIGN OF X 
        AND  80H        ; (CY IS OFF) 
        JR   NZ,CP10    ; X IS NEGATIVE 
        BIT  7,E 
        RET  NZ         ; Y IS NEGATIVE 
; 
; X AND Y ARE BOTH POSITIVE, COMPARE EXPONENTS 
; 
 \f

        LD   A,(IX+7) 
        CP   (IY+7) 
        RET  NZ         ; EXP'S NOT = 
; 
; COMPARE X FRACTION TO Y FRACTION 
; 
        LD   A,D        ; MS BYTE 
        CP   E          ; (SIGNS ARE EQUAL) 
        RET  NZ 
        PUSH IX         ; SET UP PTRS 
        PUSH IY 
        JR   CP20 
; 
; X IS NEGATIVE, CHECK SIGN OF Y 
; 
CP10    XOR  E          ; TEST SIGN, SET NZ 
        RLA             ; SIGN BIT IN CY 
        RET  C          ; Y WAS POSITIVE 
; 
; BOTH SIGNS NEGATIVE, TEST EXPONENTS 
; 
       LD   A,(IY+7) 
       CP   (IX+7) 
       RET  NZ 
; 
; COMPARE Y FRACTION TO X FRACTION 
; 
        LD   A,E 
        CP   D 
        RET  NZ 
        PUSH IY         ; SET UP PTRS 
        PUSH IX 
; 
; LOOP TO COMPARE 6 FRACTION BYTES 
; 
CP20    POP  HL         ; GET PTRS 
        POP  DE 
        INC  HL 
        INC  DE 
        LD   B,6        ; COUNTER 
CP30    LD   A,(DE) 
        CP   (HL) 
        RET  NZ 
        INC  HL 
        INC  DE 
        DJNZ CP30 
        RET 
*H NORMALIZE 
; 
; NORMLZ  NORMALIZES AN ACCUM BY SHIFTING LEFT 
; 
;   INPUT:  IX  PTS TO ACCUM (NORMLZ,NORML1) 
;           HL  PTS TO ACCUM (NORML2) 
;           C   CONTAINS BIASED EXP (NORML1,NORML2) 
;   OUTPUT: NORMAL RETURN - NZ & NC 
;           ZERO FRACTION -  Z & NC 
;           EXP UNDERFLOW - NZ &  C 
;           C   CONTAINS UPDATED EXPONENT 
;           (IX+7) CONTAINS UPDATED EXPONENT C UNDER C 
; 
 \f

NORMLZ  LD   C,(IX+7)   ; GET EXPONENT 
NORML1  PUSH IX         ; PT TO ACCUM 
        POP  HL 
NORML2  LD   A,(HL)     ; GET MS BYTE 
        AND  A 
        JR   NZ,NOR15   ; ALREADY NORMALIZED 
        LD   B,12       ; MAX COUNT 
        XOR  A          ; CLEAR A 
NOR10   DEC  C          ; DECR EXPONENT 
        JR   Z,NOR20    ; UNDERFLOW 
        CALL SLD1       ; SHIFT LEFT 
        INC  HL         ; PT TO 1ST BYTE 
        LD   A,(HL)     ; GET MS BYTE 
        AND  A 
        JR   NZ,NOR15   ; NORMALIZED 
        DJNZ NOR10      ; COUNTER NOT 0 
NOR15   LD   (IX+7),C   ; STORE EXPONENT 
        RET 
; 
; UNDERFLOW.  HL PTS TO MS BYTE, A CONTAINS MS BYTE 
; 
NOR20   INC  B          ; CALC BYTES LEFT 
        SRL  B 
NOR30   INC  HL         ; ADVANCE PTR 
        OR   (HL)       ; COLLECT REMAINING BITS 
        DJNZ NOR30      ; COUNT NOT 0 
        RET  Z          ; FRACTION WAS ZERO 
        SCF 
        RET             ; (UNDERFLOW) 
*H HALF 
; 
; HALF  DIVIDES A FLOATING POINT NUMBER BY 2 
;   INPUT MUST BE POSITIVE (0 IN SIGN DIGIT) 
; 
;   INPUT:  IX  PTS TO X (HALF) 
;   OUTPUT: INPUT REPLACED BY X/2 
;           FLAGS SET ACCORDING TO NORMLZ 
; 
HALF    AND  A          ; CLEAR CY 
        CALL SRB        ; DIVIDE FRACTION BY 2 
        CALL NORMLZ     ; NORMALIZE RESULT 
        RET 
*H SHIFT UTILITIES 
; 
; SLD SHIFT LEFT DIGIT 
; 
;   INPUT:  IX  PTS TO ACCUM (SLD) 
;           HL  PTS TO ACCUM (SLD1) 
;           A   CONTAINS DIGIT TO SHIFT IN 
;   OUTPUT: A   CONTAINS DIGIT SHIFTED OUT 
;           HL  PTS TO 1 LESS THAN MS BYTE 
; 
SLD     PUSH IX         ; SET PTR TO ACCUM 
        POP  HL 
SLD1    PUSH BC         ; SAVE BC 
        LD   BC,6 
        ADD  HL,BC      ; PT TO RIGHT END 
        LD   B,7        ; LOOP COUNTER 
SLD10   RLD             ; ROT LEFT 
 \f

        DEC  HL         ; PT TO NEXT BYTE 
        DJNZ SLD10      ; COUNTER NOT 0 
        POP  BC         ; RESTORE BC 
        RET 
; 
; SRD  SHIFT RIGHT DIGIT 
; 
;   INPUT:  IX  PTS TO ACCUM (SRD) 
;           HL  PTS TO ACCUM (SRD1) 
;           A   CONTAINS DIGIT TO SHIFT IN 
;   OUTPUT: A   CONTAINS DIGIT SHIFTED OUT 
;           HL  PTS TO 1 MORE THAN LS BYTE 
; 
SRD     PUSH IX         ; SET PTR TO ACCUM 
        POP  HL 
SRD1    PUSH BC         ; SAVE BC 
        LD   B,7        ; COUNTER 
SRD10   RRD             ; ROT RIGHT 
        INC  HL 
        DJNZ SRD10      ; COUNTER NOT 0 
        POP  BC         ; RESTORE RC 
        RET 
; 
; SLB SHIFT LEFT BIT 
; 
;   INPUT:  IX  PTS TO ACCUM (SLB) 
;           HL  PTS TO ACCUM (SLB1) 
;           CY  CONTAINS BIT TO SHIFT IN 
;   OUTPUT: CY  CONTAINS BIT SHIFTED OUT 
;           HL  PTS TO 1 LESS THAN MS BYTE 
; 
SLB     PUSH IX         ; SET PTR TO ACCUM 
        POP  HL 
SLB1    PUSH BC         ; SAVE BC 
        LD   BC,6 
        ADD  HL,BC      ; PT TO RIGHT END 
        LD   B,7        ; LOOP COUNTER 
SLB10   LD   A,(HL)     ; GET BYTE 
        ADC  A,A        ; SHIFT LEFT 
        DAA 
        LD   (HL),A     ; REPLACE 
        DEC  HL         ; PT TO NEXT BYTE 
        DJNZ SLB10      ; COUNTER NOT 0 
        POP  BC         ; RESTORE BC 
        RET 
; 
; SRB  SHIFT RIGHT BIT 
; 
;   INPUT:  IX  PTS TO ACCUM (SRB) 
;           HL  PTS TO ACCUM (SRB1) 
;           CY  CONTAINS BIT TO SHIFT IN 
;   OUTPUT: CY  CONTAINS BIT SHIFTED OUT 
;           HL  PTS TO 1 MORE THAN LS BYTE 
; 
SRB     PUSH IX         ; SET PTR TO ACCUM 
        POP  HL 
SRB1    PUSH BC         ; SAVE BC 
        LD   B,7        ; COUNTER 
SRB10   LD   A,(HL)     ; GET BYTE 
        RRA             ; SHIFT 
 \f

        RR   C          ;  SAVE CY IN C 
        BIT  7,A 
        JR   Z,SRB20    ; 0 SHIFTED INTO UPPER 
        SUB  30H        ; CORRECTION 
SRB20   BIT  3,A 
        JR   Z,SRB30    ; 0 SHIFTED INTO LOWER 
        SUB  3          ; CORRECTION 
SRB30   RL   C          ; GET CY 
        LD   (HL),A     ; STORE BYTE 
        INC  HL 
        DJNZ SRB10      ; COUNTER NOT 0 
        POP  BC         ; RESTORE BC 
        RET 
*H MOVE UTILITIES 
; 
; MOVE ROUTINES 
; 
STO4    LD   DE,TEMP4 
        JP   STO 
STO5    LD   DE,TEM5 
        JP   STO 
STO6    LD   DE,TEM6 
STO     PUSH IX 
        POP  HL         ; SET SRC PTR 
MOV     LD   BC,8 
        LDIR 
        RET 
LD      PUSH IX 
        POP  DE         ; SET DEST PTR 
        JP   MOV 
; 
; SPECIALIZED LOAD ROUTINES, LOAD AC1 AND AC2 WITH ABS VALUE 
; 
STA1    PUSH IX         ; SOURCE WILL BE (IX) 
        JR   ST1 
STA2    PUSH IX         ; SOURCE WILL BE (IX) 
        JR   ST2 
STYA1   PUSH IY         ; SOURCE WILL BE (IY) 
ST1     POP  HL 
MV1     LD   DE,AC1     ; DEST IS AC1 
        CALL MOV 
        LD   HL,AC1 
        LD   D,(HL)     ; SAVE MS BYTE IN D 
        RES  7,(HL)     ; CLEAR SIGN BIT 
        RET 
STYA2   PUSH IY         ; SOURCE WILL BE (IY) 
ST2     POP  HL 
MV2     LD   DE,AC2     ; DEST IS AC2 
        CALL MOV 
        LD   HL,AC2 
        LD   E,(HL)     ; SAVE MS BYTE IN E 
        RES  7,(HL)     ; CLEAR SIGN BIT 
        RET 
*H BOOLEAN 
; 
; LOGICAL OPERATORS 
; 
IOR     LD   A,(IX) 
        OR   (IX+1) 
        OR   (IY) 
        OR   (IY+1) 
        JP   INE1 
 \f

IAND    LD   A,(IX) 
        OR   (IX+1) 
        JP   Z,IZERO    ; X IS ZERO 
        LD   A,(IY) 
        OR   (IY+1) 
        JP   INE1 
INOT    LD   A,(IX) 
        OR   (IX+1) 
        JR   IEQ1 
OR      LD   A,(IX+7) 
        OR   (IY+7) 
        JP   NE1 
AND     LD   A,(IX+7) 
        AND  A 
        JP   Z,ZERO     ; X IS ZERO 
        LD   A,(IY+7) 
        AND  A 
        JR   NE1 
NOT     LD   A,(IX+7) 
        AND  A 
        JR   EQ1 
; 
; RELATIONAL OPERATORS 
; 
SGT     CALL SCP 
        JR   IGT1 
SLE     CALL SCP 
        JR   ILE1 
SLT     CALL SCP 
        JR   ILT1 
SGE     CALL SCP 
        JR   IGE1 
SEQ     CALL SCP 
        JR   IEQ1 
SNE     CALL SCP 
        JR   INE1 
IGT     CALL ICP 
IGT1    JR   Z,IZERO 
        JR   C,IZERO 
        JR   IONE 
ILE     CALL ICP 
ILE1    JR   Z,IONE 
        JR   C,IONE 
        JR   IZERO 
ILT     CALL ICP 
ILT1    JR   C,IONE 
        JR   IZERO 
IGE     CALL ICP 
IGE1    JR   C,IZERO 
        JR   IONE 
IEQ     CALL ICP 
IEQ1    JR   Z,IONE 
        JR   IZERO 
INE     CALL ICP 
INE1    JR   Z,IZERO 
        JR   IONE 
GT      CALL CP 
GT1     JR   Z,ZERO 
        JR   C,ZERO 
        JR   ONE 
 \f

LE      CALL CP 
LE1     JR   Z,ONE 
        JR   C,ONE 
        JR   ZERO 
LT      CALL CP 
LT1     JR   C,ONE 
        JR   ZERO 
GE      CALL CP 
GE1     JR   C,ZERO 
        JR   ONE 
EQ      CALL CP 
EQ1     JR   Z,ONE 
        JR   ZERO 
NE      CALL CP 
NE1     JR   Z,ZERO 
        JR   ONE 
*H CONSTANT FUNCTIONS 
; 
; PRODUCE UNITY RESULT 
; 
IONE    LD   (IX),1 
        DD   (IX+1),0 
        RET 
ONE     LD   B,7 
        CALL ZERO1 
        LD   (HL),81H 
        LD   (IX),1 
        RET 
; 
; PRODUCE ZERO RESULT 
; 
IZERO   LD   (IX),0 
        LD   (IX+1),0 
        RET 
ZERO    LD   B,8 
ZERO1   PUSH IX         ; PT TO RESULT 
        POP  HL 
ZER10   LD   (HL),0 
        INC  HL 
        DJNZ ZER10 
        RET 
; 
; PRODUCE INFINITE RESULT 
; 
INF     PUSH IX         ; SET PTR 
        POP  HL 
        RL   (HL)       ; GET OLD SIGN 
        LD   (HL),18 
        RR   (HL)       ; REPLACE SIGN 
        INC  HL 
        LD   A,99H 
        LD   B,6 
INF10   LD   (HL),A 
        INC  HL 
        DJNZ INF10 
        LD   (HL),0FFH  ; HIGHEST EXP 
        RET 
; 
; FLAG OVERFLOW ERROR, STORE INFINITY 
; 
 \f

OVERA   EX   AF,AF'     ; GET SIGN OF RESULT 
        LD   (IX),A     ; STORE IT 
OVER    LD   HL,ERROR 
        SET  6,(HL)     ; FLAG OVERFLOW 
        JP   INF 
; 
; FLAG UNDERFLOW ERROR, STORE ZERO 
; 
UNDER   LD   HL,ERROR 
        SET  5,(HL)    ; FLAG UNDERFLOW 
        JP   ZERO 
*H CONSTANTS AND WORK AREAS 
C1      DEFW 1 
        DEFW 0 
        DEFW 0 
        DEFW 8100H 
C0      DEFW 0 
        DEFW 0 
        DEFW 0 
        DEFW 0 
C _5     DEFW 5          ; .5 
        DEFW 0 
        DEFW 0 
        DEFW 8000H 
SEED    DEFW 0          ; 0 
        DEFW 0 
        DEFW 0 
        DEFW 0 
SEED10  EQU  SEED+6 
CRNDA   DEFW 1403H      ; 31415 92653 581 
        DEFW 9215H 
        DEFW 3565H 
        DEFW 8081H 
CRNDC   DEFW 7102H      ; 27182 81828 459 
        DEFW 8182H 
        DEFW 8482H 
        DEFW 8059H 
CRNDCO  EQU  CRNDC+6 
SAVE    DEFS 2 
AC1     DEFS 8 
AC10    EQU  AC1+6 
AC1E    EQU  AC1+7      ; EXPONENT BYTE 
AC2     DEFS 8 
AC20    EQU  AC2+6 
AC2E    EQU  AC2+7      ; EXPONENT BYTE 
TEMP0   DEFS 8 
TEMP00  EQU  TEMP0+6 
TEMP0E  EQU  TEMP0+7 
TEMP1   DEFS 8 
TEMP10  EQU  TEMP1+6 
TEMP2   DEFS 8 
TEMP20  EQU  TEMP2+6 
TEMP3   DEFS 8 
TEMP30  EQU  TEMP3+6 
TEMP4   DEFS 8 
TEMP5   DEFS 8 
TEMP6   DEFS 8 
 \f

; 
; REFERENCES 
; 
        EXTERNAL        ERROR,ICP,SCP 
        GLOBAL          ADD,SUB,RSUB,MULT,REC,DIVI 
        GLOBAL          MLDIG,MDTL 
        GLOBAL          FIX,FIXA,FLOAT,FLOAT1,CP,MAD 
        GLOBAL          GT,LE,LT,GE,EQ,NE,OR,AND,NOT 
        GLOBAL          IGT,ILE,ILT,IGE,IEQ,INE,IOR,IAND,INOT 
        GLOBAL          SGT,SLE,SLT,SGE,SEQ,SNE 
        GLOBAL          SEED,SEED10,CRNDA,CRNDC0,C _5,SAVE,C1,C0 
        GLOBAL          OVER,UNDER,ZERO,ONE,INF 
        GLOBAL          NORMLZ,NORML1,NORML2,SLD,SRB,HALF 
        GLOBAL          STO4,STO5,STO6,STO,LD,SRD 
        GLOBAL          TEMP4,TEMP5,TEMP6,AC1,AC10,AC2,AC20 
 \f

****************************************** 
DMATH2.S 
created  770801;  last modified  791023 
****************************************** 
 
 
*H POWER 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
;  X TO THE Y POWER 
; 
;   INPUT:  IX  PTS TO X 
;           IY  PTS TO Y 
;   OUTPUT: IX  PTS TO X Y 
;   ERRORS: NONE DIRECTLY 
;   SPECIAL CASES:  IF Y IS 0, RETURN 1 
;   ALGORITHM:  IF Y IS AN EXACT INTEGER -32768 <= Y < 32768 
;               THEN USE A SEQUENCE OF SQUARING AND 
;               MULTIPLYING BY X TO PRODUCE RESULT 
;       OTHERWISE, RESULT IS EXP(Y*LOG(X)) 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; DETERMINE IF Y IS AN INTEGER 
; 
POW     PUSH IY         ; SAVE PTR TO Y 
        PUSH IX         ; SAVE PTR TO X 
        PUSH IY         ; PT TO Y 
        POP  IX 
        CALL FIXA       ; CONVERT TO INTEGER 
        POP  IX         ; RESTORE IX 
        JR   Z,POW10    ; Y WAS AN INTEGER 
; 
; FOR NONINTEGER Y, TAKE EXP(Y*LOG(X)) 
; 
        CALL LOG        ; LOG OF X 
        POP  IY         ; RESTORE IY 
        CALL MULT       ; MPY BY Y 
        CALL EXP        ; EXP OF PRODUCT 
        RET 
; 
; Y IS INTEGER, SET UP FOR LOOP, GET MAGNITUDE 
; 
POW10   XOR  A          ; CHECK FOR 0 
        POP  IY         ; RESTORE IY 
        CP   (IY+7) 
        JP   Z,ONE      ; X TO 0 POWER 
        PUSH HL         ; SAVE Y 
        BIT  7,H 
        JR   Z,POW15    ; Y IS POSITIVE 
        EX   DE,HL      ; NEGATE Y 
        LD   HL,0 
        AND  A 
        SBC  HL,DE 
        EX   (SP),HL    ; SAVE NEGATED Y INSTEAD 
        CALL REC        ; CALC 1/X 
POW15   CALL ST04       ; SAVE COPY OF X 
        POP  HL         ; GET Y 
        LD   B,16       ; SET COUNTER 
 \f

; 
; LOOK FOR FIRST BIT 
; 
POW20   PUSH BC         ; SAVE COUNTER 
        ADD  HL,HL      ; SHIFT Y LEFT 1 
        JR   C,POW40    ; 1 BIT FOUND 
        POP  BC         ; GET COUNTER 
        DJNZ POW20      ; COUNTER NOT 0 
        JP   ONE        ; THIS JUMP SHOULD NOT HAPPEN 
; 
; SQUARE FOR EACH ZERO BIT 
; SQUARE AND MULTIPLY FOR EACH 1 BIT 
; 
POW30   PUSH BC         ; SAVE COUNTER 
        ADD  HL,HL      ; SHIFT Y LEFT 1 
        PUSH HL         ; SAVE Y 
        PUSH AF         ; SAVE CY 
        CALL STO5       ; SAVE COPY OF ACCUM 
        LD   IY,TEM5 
        CALL MULT       ; SQUARE X 
        POP  AF         ; GET CY 
        JR   NC,POW35   ; WAS A 0 BIT 
        CALL MULT4      ; MPY BY X 
POW35   POP  HL         ; GET Y 
POW40   POP  BC         ; GET COUNTER 
        DJNZ POW30      ; COUNTER NOT 0 
        RET 
; 
; IPOW  POWERS FOR INTEGER ARGUMENTS 
;   USES REAL POW ROUTINE BY FLOATING ARGS 
;   IN TEMP5, TEMP6, (UNUSED BY POW WHEN Y 
;   IS INTEGER), CALLING POW, AND FIXING RESULT 
; 
IPOW    PUSH IX         ; SAVE ORIGINAL PTR 
        LD   L,(IY)     ; GET Y 
        LD   H,(IY+1) 
        LD   IX,TEMP6 
        CALL FLOAT1     ; FLOAT Y IN TEMP6 
        POP  IX         ; GET ORIGINAL PTR 
        PUSH IX 
        LD   L,(IX)     ; GET X 
        LD   H,(IX+1) 
        LD   IX,TEMP5 
        CALL FLOAT1     ; FLOAT X IN TEMP5 
        LD   IY,TEMP6   ; PT TO Y 
        CALL POW        ; CALL REAL ROUTINE 
        CALL FIX        ; FIX RESULT 
        POP  IX         ; GET ORIGINAL PTR 
        LD   (IX),L     ; STORE RESULT 
        LD   (IX+1),H 
        RET 
*H SQUARE ROOT 
 \f

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; SQUARE ROOT FUNCTION 
; 
;   INPUT:  IX PTS TO X 
;   OUTPUT: IX PTS TO SQR(X) 
;   ERRORS: X IS NEGATIVE, RETURNS SQR(ABS(X)) 
;   SPECIAL CASES:  X IS 0 
;   ALGORITHM:  INPUT IS SCALED TO .1 <= X < 1 
;       BY REMOVING THE EXPONENT.  HALF THE 
;       EXPONENT IS ADDED TO THE RESULT EXPONENT 
;       AND THE RESULT IS MULTIPLIED BY SQR(10) 
;       IF THE ORIGINAL EXP WAS ODD. 
;       AN INITIAL APPROXIMATION IS GIVEN BY 
;       A 1ST ORDER POLYNOMIAL, AND IMPROVED TO 
;       REQUIRED ACCURACY IN 4 ITERATIONS OF 
;       MEWTON'S METHOD 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; CHECK VALID ARGUMENTS 
; 
SQR     LD   A,(IX+7) 
        OR   A 
        JP   Z,ZERO     ; ZERO INPUT 
        BIT  7,(IX) 
        CALL NZ,SQERR   ; NEGATIVE INPUT 
; 
; SCALE BY STRIPPING EXPONENT 
; 
        PUSH AF         ; SAVE ORIGINAL EXP 
        LD   (IX+7),80H ; SET ZERO EXP 
; 
; CALC INITIAL APPROX 
; 
        CALL STO4       ; SAVE X 
        PUSH IX 
        LD   IX,TEMP4 
        CALL HALF       ; CALC X/2 IN TEMP4 
        POP  IX 
        LD   IY,PSQ00 
        CALL ADD; INIT APPROX.
; 
; PERFORM 4 ITERATIONS 
; 
        LD   B,4 
SQ10    PUSH BC         ; SAVE COUNTER 
        CALL STO5       ; SAVE LAST APPROX IN TEMP5 
        LD   HL,TEMP4 
        CALL LD         ; GET X/2 
        LD   IY,TEMP5 
        CALL DIVI       ; DIVIDE BY LAST APPROX 
        PUSH IX 
        LD   IX,TEMP5 
        CALL HALF       ; DIVIDE LAST APPROX BY 2 
        POP   IX 
        CALL ADD        ; CALC NEW APPROX 
        POP  BC 
        DJNZ SQ10       ; COUNTER NOT 0 
 \f

; 
; CALC EXPONENT, SCALE RESULT 
; 
        POP  AF         ; GET ORIGINAL EXP 
        AND  A 
        RRA             ; DIVIDE BY TWO 
        RR   B          ; SAVE CY 
        ADD  A,40H      ; CORRECT THE BIAS 
        LD   (IX+7),A   ; STORE IT 
        BIT  7,B        ; TEST ODD OR EVEN 
        RET  Z          ; ORIGINAL EXP EVEN 
        LD   IY,SQR10 
        CALL MULT       ; MPY BY SQR(10) 
        RET 
; 
; SQUARE ROOT OF NEGATIVE NUMBER 
; 
SQERR   LD   HL,ERROR 
        SET  3,(HL)     ; FLAG ERROR 
        RES  7,(IX)     ; MAKE POSITIVE 
        RET 
*H EXP 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; EXPONENTIATION ROUTINE 
; 
;   INPUT:  IX  PTS TO X 
;   OUTPUT: IX  PTS TO E X 
;   ERRORS: OVER/UNDERFLOW IN HANDLING EXPONENT PART 
;   ALGORITHM:  X:=X*2*LOG BASE 10 OF E 
;       SAVE:=INT(X) 
;       X:=FRACTION PART(X) / 2 
;       X:=10 X, WHERE 0 <= X < .5 
;       IF SAVE IS ODD THEN X:=X*SQR(10) 
;       X:=X*10 INT(SAVE/2) 
; 
;       THE APPROXIMATION TO 10 X IS GIVEN BY : 
;               (Q(X 2) + X*P(X 2)) / (Q(X 2) - X*P(X 2)) 
;       WHERE Q IS 3RD ORDER POLYNOMIAL, P IS 2ND ORDER. 
;       REFERENCE IS "COMPUTER APPROXIMATIONS", HART, JOHN F. 
;           ET AL, FUNCTION NUMBER 1444 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; CONVERT E X TO 10 X 
; 
EXP     LD   IY,LOGE2   ; MULT BY 2*LOG10(E) 
        CALL MULT 
; 
; GET 8 BIT 2'S COMPL INTEGER PART IN A 
; 
        CALL BRK        ; BREAK INTEGER AND FRACTION PARTS 
        JP   C,EXERR1   ; INTEGER PART > 16 bits 
        LD   A,H 
        RLC  L          ; SIGN BIT IN CY 
        ADC  A,0 
        JP   NZ,EXERR2  ; INTEGER > 8 BITS 
        LD   A,L 
        RRCA            ; RESTORE 8 BIT INTEGER 
        PUSH AF         ; SAVE IT 
 \f

; 
; SCALE FRACTION PART TO 0 <= X < .5 
; 
        XOR  A 
        CP   (IX+7) 
        JR   Z,EX10     ; FRACTION IS ZERO 
        CALL HALF 
        JP   C,UNDER    ; UNDERFLOW 
; 
; EVALUATE RATIONAL APPROX. TO 10 X 
; 
EX10    CALL XX2        ; STORE X, X 2 IN TEMP4, 5 
        LD   IY,PEX02 
        LD   B,2        ; 2ND ORDER POLY 
        CALL POLY       ; EVALUATE P(X 2) 
        CALL MULT4      ; CALC. X*P(X 2) 
        CALL STO4       ; SAVE X*P IN TEMP4 
        LD   HL,TEMP5 
        CALL LD         ; GET X 2 
        LD   IY,QEX02 
        LD   B,2        ; 3RD ORDER POLY(1) 
        CALL POLY1      ; EVALUATE Q(X 2) 
        CALL STO5       ; SAVE Q IN TEMP5 
        LD   IY,TEMP4 
        CALL SUB 
        CALL STO6       ; SAVE Q-XP IN TEMP6 
        LD   HL,TEMP5    
        CALL LD         ; GET Q 
        LD   IY,TEMP4 
        CALL ADD        ; CALC. Q+XP 
        LD   IY,TEMP6 
        CALL DIVI       ; FINAL RESULT 
; 
; POSSIBLE SCALE BY SQR(10) 
; 
        POP  AF         ; GET 8 BIT INTEGER 
        SRA  A          ; DIVIDE BY 2 
        PUSH AF         ; SAVE INTEGER 
        LD   IY,SQR10 
        CALL C,MULT     ; INTEGER WAS ODD 
; 
; ADD INTEGER PART TO RESULT EXPONENT 
; 
        POP  BC         ; PUT INTEGER IN B 
        LD   A,(IX+7)   ; GET EXP 
        SUB  80H        ; REMOVE BIAS 
        ADD  A,B        ; ADD INTEGER PART 
        JP   PE,EXERR3  ; OVER/UNDERFLOW 
        ADD  A,80H      ; ADD BIAS
        JP   Z,UNDER    ; UNDERFLOW 
        LD   (IX+7),A   ; STORE EXP 
        RET 
; 
; EXP ERRORS 
; 
EXERR1  EX   AF,AF'     ; GET ORIGINAL SIGN 
        LD   H,A 
EXERR2  BIT  7,H 
        JP   NZ,UNDER   ; - SIGN 
        JP   OVER 
EXERR3  JP   P,UNDER    ; + SIGN AFTER OVERFLOW 
        JP   OVER 
 \f

*H LOG 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; LOG ROUTINE 
; 
;   INPUT:  IX  PTS TO X 
;   OUTPUT: IX  PTS TO NATURAL LOG OF X 
;   ERRORS: X IS NEGATIVE, RETURN LOG(ABS(X)) 
;           X IS ZERO, RETURN NEGATIVE OVERFLOW 
;   SPECIAL CASES:  X IS 1, RETURN ZERO 
;   ALGORITHM:  SAVE:=INT(X) 
;       X:=SQR(10)*FRACTION-PART(X) 
;       X:=LOG BASE E (X), WHERE 1/SQR(10) < X < SQR(10) 
;       X:=X - LOG BASE E(SQR(10)) + SAVE*LOG BASE E(10) 
; 
;       LOG IS APPROXIMATED BY : 
;               Z*P(Z 2) / Q(Z 2)  WHERE Z = (X-1) / (X+1) 
;       AND P IS A 3RD ORDER POLYNOMIAL, AND Q IS 4TH ORDER. 
;       REFERENCE FUNCTION IS 2686. 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; CHECK FOR VALID ARGUMENTS 
; 
LOG     BIT  7,(IX) 
        CALL NZ,LGERR1  ; NEGATIVE ARG 
        LD   IY,C1 
        CALL CP 
        JP   Z,ZERO     ; LOG(1) 
        LD   A,(IX+7)   ; GET EXPONENT 
        OR   A 
        JP   Z,LGERR2   ; ZERO ARG 
; 
; TAKE LOG OF EXPONENT PART 
; 
        SUB  80H        ; REMOVE BIAS 
        LD   L,A        ; PUT IN HL 
        LD   H,0        ; SIGN EXTEND 
        JR   NC,LO10    ; + SIGN 
        LD   H,0FFH 
LO10    PUSH HL         ; SAVE INTEGER 
; 
; SCALE TO 1/SQR(10) < X < SQR(10) 
; 
        LD   (IX+7),80H ; SCALE TO 0 < X < 1 
        LD   IY,SQR10 
        CALL MULT 
; 
; APPROXIMATION FOR LOGARITHM 
        CALL STO4       ; SAVE X IN TEMP4 
        PUSH IX         ; SAVE PTR 
        LD   IX,TEMP4 
        LD   IY,C1 
        CALL ADD        ; X+1 IN TEMP4 
        POP  IX 
        LD   IY,C1 
        CALL SUB        ; x-1 IN (IX) 
        LD   IY,TEMP4 
        CALL DIVI 
 \f

        CALL XX2        ; STORE Z,Z 2 IN TEMP4,5 
        LD   IY,QL003 
        LD   B,3 
        CALL POLY1      ; EVALUATE Q(Z 2) 
        CALL STO6       ; Q IN TEMP6 
        LD   HL,TEMP5 
        CALL LD         ; LOAD Z 2 
        LD   IY,PL003 
        LD   B,3 
        CALL POLY       ; EVALUATE P(Z 2) 
        CALL MULT4      ; CALC. Z*P(Z 2) 
        LD   IY,TEMP6 
        CALL DIVI       ; CALC ZP/Q 
        LD   IY,LNSQ10 
        CALL SUB        ; SUB LOGE(SQR(10)) 
        CALL STO4       ; SAVE IN TEMP4 
; 
; CONVERT 16 BIT EXPONENT PART TO FLOATING PT 
; 
        POP  HL         ; GET INTEGER 
        CALL FLOAT1     ; FLOAT IT 
        LD   IY,LN10 
        CALL MULT       ; MPY BY LOG BASE E(10) 
        LD   IY,TEMP4 
        CALL ADD        ; FINAL RESULT 
        RET 
; 
; ERRORS 
; 
LGERR1  LD   HL,ERROR 
        SET  2,(HL)     ; FLAG LOG OF NEG 
        RES  7,(HL)     ; TAKE ABS VALUE 
        RET 
LGERR2  SET  7,(IX)     ; SET NEGATIVE SIGN 
        JP   OVER       ; LOG OF ZERO 
*H TANGENT 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; TANGENT ROUTINE 
; 
;   INPUT:  IX  PTS TO X (IN RADIANS) 
;   OUTPUT: IX  PTS TO TAN(X) 
;   ERRORS: NONE DIRECTLY 
;   ALGORITHM:  X := X*4/PI 
;       SAVE := INT(X) LAND 3  (SAVE LOW 2 BITS ONLY) 
;       X := FRACTION-PART(X) 
;       IF SAVE IS 0,2 THEN X := 1-X 
;       X := TAN(X*PI/4),  WHERE 0 <= X <= PI/4 
;       IF SAVE IS 0,3 THEN X := 1/X 
;       IF SAVE IS 0,1 THEN X := -X 
; 
;       THE APPROXIMATION TO TAN(X*PI/4) IS GIVEN BY: 
;                X*P(X 2) / Q(X 2) 
;       WHERE P IS ORDER 3 POLYNOMIAL, Q IS ORDER 4 
;       REFERENCE FUNCTION IS 4286 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
 \f

; 
; SCALE BY 4/PI 
; 
TAN     LD   IY,FOVRPI 
        CALL MULT 
        CALL BRK        ; GET INTEGER,FRACTION 
        LD   A,L 
        PUSH AF         ; SAVE FLAG BITS 
        AND  1          ; TEST FLAG 
        JR   Z,TA10     ; FLAG WAS 0 OR 2
        LD   IY,C1 
        CALL RSUB       ; CALC. 1-FRACTION PART 
; 
; TAN APPROX 
; 
TA10    CALL XX2        ; SAVE X,X 2 IN TEMP4,5 
        LD   IY,QTA03 
        LD   B,3 
        CALL POLY1      ; EVALUATE Q(X 2) 
        CALL STO6       ; SAVE Q 
        LD   HL,TEMP5 
        CALL LD         ; GET X 2 
        LD   IY,PTA03 
        LD   B,3 
        CALL POLY       ; EVALUATE P(X 2) 
        CALL MULT4      ; CALC. X*P(X 2) 
        POP  AF         ; GET 2 BIT FLAG 
        PUSH AF 
        AND  3 
        JP   PE,TA20    ; FLAG WAS 0 OR 3 
        CALL STO4       ; SAVE X*P 
        LD   HL,TEMP6 
        CALL LD         ; GET Q  
        LD   IY,TEMP4   ; SET FOR Q/XP 
        JP   TA30 
TA20    LD   IY,TEMP6   ; SET FOR XP/Q 
TA30    CALL DIVI 
; 
; CALC. SIGN OF RESULT 
; 
        POP  AF         ; GET FLAG 
        AND  2 
        RET  Z          ; ON 0 OR 1 
        SET  7,(IX) 
        RET 
*H COSINE,SINE 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; COSINE ROUTINE 
;   EFFECTIVELY ADDS PI/2 AND CALLS SINE 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
COS     LD   IY,FOVRPI 
        CALL MULT       ; SCALE BY 4/PI 
        CALL BRK        ; GET INTEGER, FRACTION 
        LD   A,L 
        ADD  A,2        ; ADD EFFECTIVE PI/2 
        JP   SI10 
 \f

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; SINE ROUTINE 
; 
;   INPUT:  IX  PTS TO X (IN RADIANS) 
;   OUTPUT: IX  PTS TO SIN(X) 
;   ERRORS: NONE 
;   ALGORITHM:  X := X*4/PI 
;       SAVE := INT(X) LAND 7 
;       X := FRACTION-PART(X) 
;IF SAVE IS 1,3,5,7 THEN X := 1-X 
;       IF SAVE IS 0,3,4,7 THEN X := SIN(X*PI/4) 
;       IF SAVE IS 1,2,5,6 THEN X := COS(X*PI/4) 
;       IF SAVE IS 4,5,6,7 THEN X := -X 
; 
;       THE SINE APPROX FOR 0 <= X <= PI/4 IS: 
;               X*P(X 2) / Q(X 2) 
;       WHERE P IS A 3RD ORDER POLYNOMIAL, Q IS 3RD ORDER. 
;       REFERENCE FUNCTION IS 3063. 
; 
;       THE COSINE APPROX IS: 
;               P(X 2) / Q(X 2) 
;       WHERE P IS A 3RD ORDER POLY, Q IS 3RD ORDER. 
;       REFERENCE FUNCTION IS 3843. 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
SIN     LD   IY,FOVRPI 
        CALL MULT       ; SCALE BY 4/PI 
        CALL BRK        ; GET INTEGER AND FRACTION 
        LD   A,L 
SI10    PUSH AF         ; SAVE 3 BIT FLAG 
        AND  1 
        JR   Z,SI20     ; FLAG IS 0,2,4,6 
        LD   IY,C1 
        CALL RSUB       ; CALC. 1-X 
SI20    POP  AF         ; GET FLAG
        PUSH AF 
        AND  3 
        JP   PO,SI30    ; 1,2,5,6 
; 
; SIN APPROX 
; 
        CALL XX2        ; STORE X,X 2 IN TEMP4,5 
        LD   IY,QSI02 
        LD   B,2 
        CALL POLY1      ; EVALUATE Q(X 2) 
        CALL STO6       ; SAVE Q 
        LD   HL,TEMP5 
        CALL LD         ; GET X 2 
        LD   IY,PSI03 
        LD   B,3 
        CALL POLY       ; EVALUATE P(X 2) 
        CALL MULT4      ; CALC. X*P(X 2) 
        LD   IY,TEMP6 
        CALL DIVI       ; CALC. XP/Q 
        JP   SI40 
; 
; COS APPROX 
; 
 \f

SI30    CALL XX2        ; STORE X,X 2 IN TEMP4,5 
        LD   IY,QC002 
        LD   B,2 
        CALL POLY1      ; EVALUATE Q(X 2) 
        CALL STO6 
        LD   HL,TEMP5 
        CALL LD         ; GET X 2 
        LD   IY,PC003 
        LD   B,3 
        CALL POLY       ; EVALUATE P(X 2) 
        LD   IY,TEMP6 
        CALL DIVI       ; CALC. P/Q 
; 
; CALC SIGN OF RESULT 
; 
SI40    POP  AF         ; GET FLAG 
        AND  4 
        RET  Z          ; 0,1,2,3 
        SET  7,(IX) 
        RET 
*H ARCTANGENT 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; ARCTANGENT ROUTINE 
; 
;   INPUT:  IX  PTS TO X 
;   OUTPUT: IX  PTS TO ATN(X)  (IN RADIANS) 
;   ERRORS:  NONE 
;   ALGORITHM:   SAVE := SGN(X) 
;       FLAG := 0 
;       IF TAN(3*PI/8) <= X THEN X:=1/X, FLAG:=1 
;       IF TAN(PI/8) <= X THEN X:=(X-1)/(X+1), FLAG:=2 
;       X := ATN(X)  , WHERE 0 <= X <= TAN(PI/8) 
;       IF FLAG = 1 THEN X := X + PI/4 
;       IF FLAG = 2 THEN X := PI/2 - X 
;       X := X*SAVE 
; 
;       APPROXIMATION FOR ATN(X) IS: 
;               X*P(X 2) / Q(X 2) 
;       WHERE P IS 3RD ORDER POLYNOMIAL, Q IS 4TH ORDER. 
;       REFERENCE FUNCTION IS 5075 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; TAKE ABS VALUE, DETERMINE RANGE 
; 
ATN     LD   A,(IX)     ; GET SIGN 
        AND  80H 
        PUSH AF         ; SAVE SIGN 
        RES  7,(IX)     ; MAKE POSITIVE 
        LD   IY,TAPI8 
        CALL CP         ; COMPARE TO 1ST LIMIT 
        LD   B,0 
        JR   C,AT20     ; < TAN(PI/8) 
        LD   IY,TA3PI8 
        CALL CP         ; COMPARE TO 2ND LIMIT 
        JR   C,AT10     ; < TAN(3*PI/8) 
; 
; TAN(3*PI/8) <= X 
;   TAKE 1/X NOW, SUB FROM PI/2 AT END 
; 
 \f

        CALL REC        ; RECIPROCAL 
        LD   B,2        ; SET FLAG TO 2 
        JP   AT20 
; 
; TAN (PI/8) < = X < TAN(3*PI/8) 
;   CALC (X-1)/(X+1) NOW, ADD PI/4 AT END 
; 
AT10    CALL STO4       ; SAVE X IN TEMP4 
        PUSH IX 
        LD   IX,TEMP4 
        LD   IY,C1 
        CALL ADD        ; X+1 IN TEMP4 
        POP  IX 
        LD   IY,C1 
        CALL SUB        ; X-1 IN ACCUM 
        LD   IY,TEMP4 
        CALL DIVI 
        LD   B,1        ; SET FLAG TO 1 
; 
; APPROX FOR ARCTAN 
; 
AT20    PUSH BC         ; SAVE FLAG 
        CALL XX2        ; SAVE X,X 2 
        LD   IY,QAT03 
        LD   B,3 
        CALL POLY1      ; CALC. Q(X 2) 
        CALL STO6       ; SAVE Q 
        LD   HL,TEMP5 
        CALL LD         ; GET X 2 
        LD   IY,PAT03 
        LD   B,3 
        CALL POLY       ; CALC P(X 2) 
        CALL MULT4      ; X*P 
        LD   IY,TEMP6 
        CALL DIVI       ; X*P/Q 
        POP  BC         ; GET FLAG 
        BIT  0,B 
        JR   Z,AT30     ; FLAG IS 0 OR 2 
; SECOND INTERVAL (FLAG IS 1) 
        LD   IY,PI4 
        CALL ADD        ; ADD PI/4 
        JP   AT40 
AT30    BIT  1,B 
        JR   Z,AT40     ; FLAG IS 0 
; THIRD INTERVAL (FLAG IS 2) 
        LD   IY,PI2 
        CALL RSUB       ; SUB FROM PI/2 
; 
; GIVE RESULT SIGN OF ARGUMENT 
; 
AT40    POP  AF         ; GET SIGN 
        RET  Z          ; SIGN WAS POSITIVE 
        SET  7,(IX)     ; MAKE NEGATIVE 
        RET 
*H POLY 
 \f

; 
; POLYNOMIAL EVALUATOR 
; 
;   INPUT:  IX  PTS TO ACCUM 
;           IY  PTS TO HIGHEST COEFFICIENT 
;           TEMP5 CONTAINS X 
;           B   CONTAINS ORDER (ORDER-1 FOR POLY1) 
;   OUTPUT: IX  PTS TO RESULT 
;           (POLY1 ASSUMES FIRST COEFF. IS 1) 
; 
POLY    PUSH BC         ; SAVE COUNTER 
        PUSH IY         ; SAVE COEFF. PTR 
        JP   POLY10 
POLY1   PUSH BC         ; SAVE COUNTER 
        PUSH IY         ; SAVE PTR 
        CALL ADD 
        LD   IY,TEMP5   ; PT TO X 
POLY10  CALL MULT 
        POP  IY 
        POP  BC 
        LD   DE,-8      ; ADJUST PTR 
        ADD  IY,DE 
        DJNZ POLY1      ; COUNTER NOT 0 
        CALL ADD        ; FINAL ADD 
        RET 
; 
; POLYNOMIAL UTILITIES 
; 
XX2     CALL STO4       ; STORE X IN TEMP4 
        CALL MULT4      ; CALC. X 2 
        CALL STO5 
        RET 
MULT4   LD   IY,TEMP4 
        CALL MULT 
        RET 
*H CONSTANTS 
SQR10   DEFW 1603H      ; 3.1622 77660 168 
        DEFW 7722H 
        DEFW 0166H 
        DEFW 8168H 
LNSQ10  DEFW 1501H      ; 1.1512 92546 497 
        DEFW 9212H 
        DEFW 6454H 
        DEFW 8197H 
LN10    DEFW 3002H      ; 2.3025 85092 994 
        DEFW 8525H 
        DEFW 2909H 
        DEFW 8194H 
LOGE2   DEFW 6808H      ; .86858 89638 065 
        DEFW 8958H 
        DEFW 8063H 
        DEFW 8065H 
FOVRPI  DEFW 2701H      ; 1.2732 39544 735 
        DEFW 3932H 
        DEFW 4754H 
        DEFW 8135H 
TAPI8   DEFW 1404H      ; .41421 35623 731 
        DEFW 3521H 
        DEFW 3762H 
 \f

        DEFW 8031H 
TA3PI8  DEFW 4102H      ; 2.4142 13562 373 
        DEFW 1342H 
        DEFW 2356H 
        DEFW 8173H 
PI4     DEFW 8507H      ; .78539 81633 974 
        DEFW 8139H 
        DEFW 3963H 
        DEFW 8074H 
PI2     DEFW 5701H      ; 1.5707 96326 795 
        DEFW 9607H 
        DEFW 6732H 
        DEFW 8195H 
PSQ00   DEFW 7101H      ; .17157 28752 538 
        DEFW 2857H 
        DEFW 2575H 
        DEFW 8038H 
PEX00   DEFW 1705H      ; 5178.0 91991 516 
        DEFW 9180H 
        DEFW 1599H 
        DEFW 8416H 
PEX01   DEFW 3108H      ; 831.40 67212 937 
        DEFW 6740H 
        DEFW 2921H 
        DEFW 8337H 
PEX02   DEFW 8301H      ; 18.312 36015 928 
        DEFW 3612H 
        DEFW 5901H 
        DEFW 8228H 
QEX00   DEFW 4904H      ; 4497.6 33557 406 
        DEFW 3376H 
        DEFW 7455H 
        DEFW 8406H 
QEX01   DEFW 7002H      ; 2709.3 16940 852 
        DEFW 1693H 
        DEFW 0894H 
        DEFW 8452H 
QEX02   DEFW 5901H      ; 159.37 41523 603 
        DEFW 4137H       
        DEFW 3652H 
        DEFW 8303H 
; QEX03 IS 1 
PL000   DEFW 6502H      ; 265.52 24908 516 
        DEFW 2452H 
        DEFW 8590H 
        DEFW 8316H 
PL001   DEFW 2984H      ; -429.48 34828 658 
        DEFW 3448H 
        DEFW 8682H 
        DEFW 8358H 
PL002   DEFW 9701H      ; 197.64 46297 035 
        DEFW 4664H 
        DEFW 7029H 
        DEFW 8335H 
PL003   DEFW 2782H      ; -22.764 76157 115 
        DEFW 7664H 
        DEFW 7115H 
        DEFW 8215H 
QL000   DEFW 3201H      ; 132.76 12454 159 
 \f

        DEFW 1276H 
        DEFW 4245H 
        DEFW 8359H 
QL001   DEFW 5882H      ; -258.99 54899 200 
        DEFW 5499H 
        DEFW 9289H 
        DEFW 8300H 
QL002   DEFW 5801H      ; 158.60 18962 727 
        DEFW 1860H 
        DEFW 2796H 
        DEFW 8327H 
QL003   DEFW 1483H      ; -31.416 48448 282 
        DEFW 4816H 
        DEFW 8244H 
        DEFW 8282H 
; QL004 IS 1 
PTA00   DEFW 0801H      ; 10888 600.43 728 
        DEFW 6088H 
        DEFW 3704H 
        DEFW 8828H 
PTA01   DEFW 9588H      ; -89588 8.4400 677 
        DEFW 8488H 
        DEFW 0640H 
        DEFW 8677H 
PTA02   DEFW 4101H      ; 14189. 85425 276 
        DEFW 8589H 
        DEFW 5242H 
        DEFW 8576H 
PTA03   DEFW 5684H      ; -45649 31943 867 
        DEFW 3149H 
        DEFW 3894H 
        DEFW 8267H 
QTA00   DEFW 3801H      ; 13863 796.66 357 
        DEFW 7963H 
        DEFW 6366H 
        DEFW 8857H 
QTA01   DEFW 9983H      ; -39913 09.518 035 
        DEFW 0913H 
        DEFW 8051H 
        DEFW 8735H 
QTA02   DEFW 3501H      ; 13538 2.7128 051 
        DEFW 2738H 
        DEFW 8012H 
        DEFW 8651H 
QTA03   DEFW 0181H      ; -1014.6 56190 253 
        DEFW 5646H 
        DEFW 0219H 
        DEFW 8453H 
; QTA04 IS 1 
PSI00   DEFW 0602H      ; 20664 34.333 700 
        DEFW 3464H 
        DEFW 3733H 
        DEFW 8700H 
PSI01   DEFW 8181H      ; -18160 3.9879 741 
        DEFW 3960H 
        DEFW 9787H 
        DEFW 8641H 
PSI02   DEFW 5903H      ; 3599.9 30694 964 
 \f

        DEFW 3099H 
        DEFW 4969H 
        DEFW 8464H 
PSI03   DEFW 0182H      ; -20.107 48329 459 
        DEFW 4807H 
        DEFW 9432H 
        DEFW 8259H 
QSI00   DEFW 6302H      ; 26310 65.910 265 
        DEFW 6510H 
        DEFW 0291H 
        DEFW 8765H 
QSI01   DEFW 9203H      ; 39270. 24277 465 
        DEFW 2470H 
        DEFW 7427H 
        DEFW 8565H  
QSI02   DEFW 7802H      ; 278.11 91948 108 
        DEFW 9111H 
        DEFW 8194H 
        DEFW 8308H 
; QSI03 IS 1 
PC000   DEFW 2901H      ; 12905 39.465 904 
        DEFW 3905H 
        DEFW 5946H 
        DEFW 8704H 
PC001   DEFW 7483H      ; -37456 7.0391 572 
        DEFW 7056H 
        DEFW 1539H 
        DEFW 8672H 
PC002   DEFW 3401H      ; 13432. 30098 654 
        DEFW 3032H 
        DEFW 8609H 
        DEFW 8554H 
PC003   DEFW 1281H      ; -112.31 45082 334 
        DEFW 4531H 
        DEFW 2308H 
        DEFW 8334H 
QC000   DEFW 2901H      ; 12905 39.465 904 
        DEFW 3905H 
        DEFW 5946H 
        DEFW 8704H 
QC001   DEFW 3402H      ; 23467. 77310 725 
        DEFW 7767H 
        DEFW 0731H 
        DEFW 8525H 
QC002   DEFW 0902H      ; 209.69 51819 673 
        DEFW 5169H 
        DEFW 9681H 
        DEFW 8373H 
; QC003 IS 1 
PAT00   DEFW 1602H      ; 216.06 23078 972 
        DEFW 2306H 
        DEFW 8907H 
        DEFW 8372H 
PAT01   DEFW 2203H      ; 322.66 20700 133 
        DEFW 2066H 
        DEFW 0170H 
        DEFW 8333H 
PAT02   DEFW 3201H      ; 132.70 23981 640 
        DEFW 2370H 
        DEFW 1698H 
        DEFW 8340H 
 \f

PAT03   DEFW 2801H      ; 12.888 38303 416 
        DEFW 3888H 
        DEFW 3430H 
        DEFW 8216H 
QAT00   DEFW 1602H      ; 216.06 23078 972 
        DEFW 2306H 
        DEFW 8907H 
        DEFW 8372H 
QAT01   DEFW 9403H      ; 394.68 28393 123 
        DEFW 2868H 
        DEFW 3139H 
        DEFW 8323H 
QAT02   DEFW 2102H      ; 221.05 08830 284 
        DEFW 0805H 
        DEFW 0283H 
        DEFW 8384H 
QAT03   DEFW 8503H      ; 38.501 48650 835 
        DEFW 4801H 
        DEFW 0865H 
        DEFW 8235H 
; QAT04 IS 1 
; 
; REFERENCES 
; 
        GLOBAL          POW,IPOW,SQR,EXP,LOG,TAN,COS,SIN,ATN 
        EXTERNAL        ERROR,OVER,UNDER,ZERO,ONE,C1 
        EXTERNAL        ADD,SUB,RSUB,MULT,DIVI,REC 
        EXTERNAL        HALF 
        EXTERNAL        STO4,STO5,STO6,TEMP4,TEMP5,TEMP6 
        EXTERNAL        LD,CP,FIX,FIXA,FLOAT,FLOAT1,BRK 
        EXTERNAL        SRB,NORMLZ 
 \f

****************************************** 
DMATH1.S 
created  770919;  last modified  791023 
****************************************** 
 
 
*H DECIMAL TO BINARY 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,,,,,,,,,,,, 
; 
; DECIMAL TO BINARY CONVERSION 
;   INPUT:  IX POINTS TO OUTPUT AREA 
;   OUTPUT: IX POINTS TO FL PT NUMBER 
;   ERRORS: NO DIGITS IN FRACTION PART 
;           NO DIGITS IN EXPONENT 
;           EXPONENT OVERFLOW 
;           EXPONENT UNDERFLOW 
;   REGISTER ASSIGNMENT IN MAIN LOOP: 
;       C      - DECIMAL EXPONENT 
;       B      - FLAGS: BIT 6 - DIGITS FOUND 
;                       BIT 7 - FRACTION OVRFLW 
;       A      - NEW DIGIT 
;       A'     - SIGN  IN BIT 7 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
DTOB    CALL LMARK      ; MARK BEGINNING OF SCAN 
        CALL ZERO       ; CLEAR RESULT 
        XOR  A          ; CLEAR A 
        LD   B,A        ; CLEAR FLAGS 
        LD   C,80H+13   ; INIT EXPONENT 
        EX   AF,AF'     ; PUT AWAY SIGN 
        CALL LIN        ; GET FIRST CHAR 
        CP   '+' 
        JR   Z,D10      ; SIGN IS + 
        CP   '-' 
        JR   NZ,D20     ; NO SIGN 
        EX   AF,AF' 
        OR   80H        ; FLAG NEGATIVE SIGN 
        EX   AF,AF' 
; 
; LOOP TO PROCESS CHARS BEFORE DECIMAL POINT 
; 
D10     CALL LIN        ; GET NEXT CHAR 
D20     CP   '.' 
        JR   Z,D40      ; DECML PT FOUND 
        CALL DIGIT? 
        JR   C,D50      ; NOT A DIGIT 
        SET  6,B        ; FLAG DIGIT FOUND 
        BIT  7,B 
        JR   NZ,D30     ; OVERFLOW 
        CALL CNV        ; CONVERT THIS DIGIT 
        JP   D10 
D30     INC  C          ; INC DECML EXP 
        JP   D10 
; 
; LOOP TO PROCESS CHARS AFTER DECIMAL POINT 
; 
D40     CALL LIN        ; GET NEXT CHAR 
        CALL DIGIT? 
        JR   C,D50      ; NOT A DIGIT 
 \f

        SET  6,B        ; FLAG DIGIT FOUND 
        BIT  7,B 
        JR   NZ,D40     ; OVERFLOW 
        DEC  C          ; DEC DECML EXP 
        CALL CNV        ; CONVERT THIS DIGIT 
        JP   D40 
; 
; CHANGE FRACTION TO FLOATING POINT FORMAT 
; 
D50     BIT  6,B 
        JP   Z,LREST    ; NO DIGITS FOUND 
        LD   (SAVE),A   ; SAVE THIS CHAR 
        CALL NORML1 
        JR   Z,D130     ; ZERO FRACTION PART 
        LD   A,(SAVE)   ; GET CHAR AGAIN 
; 
; PROCESS EXPONENT 
;   REGISTERS: 
;       B - BIT 7 IS SIGN 
;           BIT 6 IS DIGIT-FOUND FLAG 
;           BIT 5 IS DIGIT-OVERFLOW FLAG 
;       C - IS EXP FROM FRACTION PART 
;       HL - IS ACCUM FOR D-TO-B CONVERSION 
; 
        LD   HL,0       ; INITIALIZE REGISTERS 
        LD   B,L 
        CP   'E'-'0' 
        JR   NZ,D90     ; NOT AN 'E' 
; 
; CONVERT SIGN 
; 
        CALL LIN 
        CP   '+' 
        JR   Z,D60      ; SIGN IS + 
        CP   '-' 
        JR   NZ,D70     ; NO SIGN 
        SET  7,B        ; FLAG NEG SIGN 
; 
; CONVERT DIGITS 
; 
D60     CALL LIN 
D70     CALL DIGIT? 
        JR   C,D80      ; NOT A DIGIT 
        SET  6,B        ; FLAG DIGIT FOUND 
        BIT  5,B 
        JR   NZ,D100    ; OVER OR UNDERFLOW 
        CALL MAD        ; CONVERT THIS DIGIT 
        LD   A,H        ; CHECK FOR OVERFLOW 
        AND  A 
        JP   Z,D60      ; HL < 256 
        SET  5,B        ; SET FLAG 
        JP   D60 
; 
; TEST FOR ILLEGAL EXPONENT PART 
; 
D80     BIT  6,B 
        JR   Z,D120     ; NO DIGITS FOUND 
; 
; CONVERT HL ACCUM TO 2'S COMPLEMENT 
; 
 \f

D90     BIT  7,B 
        JR   Z,D92      ; SIGN IS + 
        EX   DE,HL 
        LD   HL,0 
        AND  A 
        SBC  HL,DE 
; 
; ADD PREVIOUS EXPONENT (C) 
; CHECK FOR OVERFLOW 
; 
D92     LD   B,0 
        AND  A 
        ADC  HL,BC      ; ADD TWO EXPONENTS 
        JP   Z,UNDER    ; UNDERFLOW 
        LD   A,H 
        AND  A 
        JR   NZ,D96     ; EXP < -128 OR > 127 
; 
; STORE SIGN AND EXPONENT 
; 
        EX   AF,AF'     ; GET SIGN 
        OR   (IX) 
        LD   (IX),A     ; STORE SIGN 
        LD   (IX+7),L   ; STORE EXP 
        JP   RTN 
;  
; DETERMINE SIGN OF EXP 
; 
D96     BIT  7,H 
        JR   D105 
; 
; FINISH SCANNING DIGITS 
; 
D100    CALL LIN        ; FINISH SCANNING DIGITS 
        CALL DIGIT? 
        JR   NC,D100    ; DIGIT IS FOUND 
; 
; DETERMINE FROM SIGN BIT WHETHER OVER OR UNDER 
; 
        BIT  7,B 
D105    JR   NZ,D110    ; SIGN IS NEGATIVE 
        CALL OVER       ; FLAG ERROR 
        JP   RTN 
D110    CALL UNDER      ; FLAG ERROR 
        JP   RTN 
; 
; ILLEGAL NUMBER 
; 
D120    LD   HL,ERROR 
        SET  7,(HL) 
        JP   RTN 
; 
; ZERO 
; 
D130    CALL ZERO 
        JP   RTN 
*EJECT 
; 
; SCANNER ROUTINES 
; 
 \f

RTN     CALL LBACK      ; BACK UP POINTER BY 1 
        JP   RC2        ; GO TO SPECIAL RETURN 
; 
; DIGIT? ROUTINE CONVERTS ASCII CHAR TO 0-9 VALUE 
;    RETURNS CY ON IF NOT A DIGIT 
; 
DIGIT?  SUB  '0' 
        RET  C          ; WAS < 30H 
        CP   10 
        CCF             ; CY SET IF > 9 
        RET 
; 
; CNV ROUTINE TO MULTIPLY DECIMAL ACCUM 1 BY 10 AND ADD 
; 
CNV     CALL SLD        ; SHIFT A INTO ACCUM 
        LD   A,(IX)     ; GET HIGH BYTE 
        AND  A 
        RET  Z          ; < 13 DIGITS 
        SET  7,B        ; FLAG DIGIT OVERFLOW 
        RET 
*H BINARY TO DECIMAL 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; BCD TO DECIMAL CONVERSION 
; 
;   INPUT:  IX PTS TO FL PT NUMBER 
;           HL PTS TO OUTPUT AREA 
;   OUTPUT: FL PT NUMBER IS MODIFIED 
;           OUTPUT AREA IS 19 BYTES: 
;               1 SIGN (SPACE OR -) 
;               13 DIGITS OF FRACTION 
;               1  "E" 
;               1  SIGN OF EXPONENT (+ OR -) 
;               3  DIGITS OF EXPONENT (LEADING ZEROS) 
;           EXPONENT IS FOR DECIMAL PT AFTER FIRST DIGIT 
;           A IS 2'S COMPLEMENT EXPONENT (-128<=A<=126) 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; CONVERT SIGN 
; 
BTOD    BIT  7,(IX)     ; TEST SIGN        
        LD   (HL), ' '  ; DEFAULT SIGN 
        JR   Z,BD10     ; + SIGN 
        LD   (HL),'-'   ; - SIGN 
BD10    INC  HL 
; 
; UNPACK FRACTION PART 
; 
        EX   DE,HL      ; OUTPUT PTR IN DE 
        CALL SLD        ; SHIFT OUT SIGN BYTE 
        LD   B,13       ; COUNTER 
        LD   A,'0' 
BD20    CALL SLD        ; GET A DIGIT 
        LD   (DE),A     ; OUTPUT IT 
        INC  DE 
        DJNZ BD20       ; COUNTER NOT 0 
; 
 \f

; 
; CONVERT EXPONENT SIGN, GET SIGN MAGNITUDE EXP 
; 
        EX   DE,HL      ; OUTPUT PTR IN HL 
        LD   (HL),'E' 
        INC  HL 
        LD   (HL),'+'   ; DEFAULT SIGN 
        LD   A,(IX+7)   ; GET BIASED EXP 
        AND  A 
        JR   Z,BD30     ; ZERO EXPON 
        SUB  81H        ; REMOVE BIAS, DECR BY 1 
        JR   NC,BD30    ; POSITIVE EXP 
        LD   (HL),'-'   ; - SIGN 
        NEG             ; CALC MAGNITUDE 
; 
; CONVERT HUNDREDS 
; 
BD30    INC  HL 
        LD   (HL),'0'   ; DEFAULT DIGIT 
        CP   100 
        JP   C,BD40     ; EXP < 100 
        LD   (HL),'1' 
        SUB  100 
; 
; DIVIDE BY 100 
; 
BD40    INC  HL 
        LD   B,2FH      ; QUOTIENT COUNTER 
        LD   C,10       ; DIVISOR 
BD50    SUB  C          ; SUBTRACT 10 
        INC  B          ; INC QUOTIENT 
        JR   NC,BD50    ; RESULT NOT NEGATIVE 
        ADD  A,C        ; RESTORE REMAINDER 
        LD   (HL),B     ; STORE QUOTIENT DIGIT 
        INC  HL 
        OR   '0' 
        LD   (HL),A     ; STORE REMAINDER DIGIT 
        LD   A,(IX+7)   ; GET EXPONENT 
        SUB  80H        ; REMOVE BIAS 
        RET 
*H RND 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; RANDOM NUMBER GENERATOR 
; 
;   INPUT:  IX  PTS TO OUTPUT/WORK AREA 
;           SEED CONTAINS PREVIOUS RANDOM NUMBER 
;   OUTPUT: IS  PTS TO RANDOM NUMBER 
;           SEED CONTAINS NEW NUMBER 
;   ERRORS: NONE 
;   ALGORITHM:  ARITHMETIC DONE MODULO 10 13 
;       X := 3141592653581 * X + 2718281828459 
;       RESULT IS DIVIDED BY 10 13, AND NORMALIZED 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; INITIALIZE REGISTERS 
; 
RND     LD   IY,CRNDA   ; PT TO MPLIER 
        PUSH IX 
 \f

        POP  DE 
        LD   HL,6 
        ADD  HL,DE      ; PT TO LS BYTE OF (IX) 
        LD   (SAVE),HL  ; SAVE FOR MLDIG 
        LD   HL,SEED    ; PT TO LAST NUMBER 
        CALL MDTL       ; SAVE MULTIPLES IN TEMPO-3 
        CALL ZERO       ; CLEAR WORK AREA 
        LD   B,7        ; SET MULTIPLY LOOP COUNTER   
        JP   RN20 
; 
; MULTIPLICATION, USING (IX) AS ACCUM, (IY) AS 
;   MULTIPLIER, (SEED) (SEED=IY-8) AS PRODUCT 
;   MULTIPLY BY 31415 92653 581  (CRNDA) 
; 
RN10    PUSH AF         ; SAVE DIGIT SHIFTED OUT 
        CALL MLDIG      ; MULTIPLY BY 2ND DIGIT 
        XOR  A 
        CALL SRD        ; SHIFT ACCUM RIGHT 
        RLA             ; PUT DIGIT IN HIGH 4 BITS 
        RLA 
        RLA 
        RLA 
        AND  OFOH 
        LD   C,A        ; SAVE UPPER DIGIT 
        POP  AF         ; GET LAST DIGIT 
        OR   C          ; COMBINE 
        LD   (IY-1),A   ; STORE IN SEED 
RN20    LD   C,(IY+6)   ; GET NEXT 2 MPLIER DIGITS 
        DEC  IY         ; DECR PTR 
        CALL MLDIG      ; MULTIPLY BY 1ST DIGIT 
        XOR  A 
        CALL SRD        ; SHIFT ACCUM RIGHT 
        DJNZ RN10 
        LD   (IY-1),A   ; STORE LAST DIGIT 
; 
; ADD 27182 81828 459  (CRNDC) TO (SEED) 
; 
        LD   B,7        ; LOOP COUNTER 
        LD   HL,CRNDC0  ; PT TO CONSTANT 
        LD   DE,SEED10  ; PT TO LS BYTE OF SEED 
        AND  A          ; CLEAR CY 
; 
; ADD LOOP 
; 
RN30    LD   A,(DE)     ; GET 2 DIGITS 
        ADC  A,(HL)     ; ADD 2 DIGITS 
        DAA 
        LD   (DE),A     ; STORE SUM 
        DEC  DE 
        DEC  HL 
        DJNZ RN30       ; COUNTER NOT 0 
; 
; SCALE AND NORMALIZE RESULT 
; 
        INC  DE         ; PT TO MS BYTE 
        AND  0FH        ; CLEAR SIGN DIGIT 
        LD   (DE),A 
        EX   DE,HL      ; PUT PTR IN HL 
        CALL LD         ; COPY SEED TO (IX) 
        LD   C,80H      ; SET EXPONENT 
        CALL NORML1     ; NORMALIZE 
        RET 
 \f

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; RANDOMIZE   USES REFRESH REGISTER TO MODIFY SEED 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
RANDMZ  LD   A,R        ; GET REFRESH REGISTER 
        OR   A 
        DAA             ; CONVERT TO DECIMAL 
        LD   (SEED10),A 
        RET 
*H INT 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; INTEGER FUNCTION -- FLOOR FUNCTION 
;   INPUT,OUTPUT: IX POINTS TO FL PT NUMBER 
;  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
INT     XOR  A 
        CP   (IX+7) 
        RET  Z          ; X WAS ZERO 
        LD   A,8DH 
        SUB  (IX+7)     ; # DIGITS RIGHT OF PT 
        RET  C          ; X >= 10 13 
        RET  Z          ; X >= 10 12 
        CP   13 
        JR   NC,INT40   ; X < 1 
        LD   B,A 
; 
; SET POINTER TO 1ST DIGIT RIGHT OF PT 
; 
        LD   A,14 
        SUB  B          ; 1+# DIGITS LEFT OF PT 
        LD   E,A 
        SRL  E          ; # BYTES TO SKIP 
        LD   D,0 
        PUSH IX         ; GET PTR 
        POP  HL 
        ADD  HL,DE 
; 
; CLEAR FIRST DIGIT IF A IS ODD 
; 
        AND  1 
        JR   Z,INT10    ; DEC PT IS BETWEEN BYTES 
        LD   A,(HL)     ; GET BYTE WITH DEC PT 
        LD   C,A        ; SAVE RIGHT HALF 
        AND  0F0H       ; CLEAR RIGHT HALF 
        LD   (HL),A     ; REPLACE IT 
        INC  HL 
        LD   A,C        ; GET RIGHT HALF 
        AND  0FH 
; 
; CLEAR REMAINING BYTES, OR-ING EACH INTO A FIRST 
; 
INT10   SRL  B          ; CALC # BYTES 
        JR   Z,INT30    ; NONE TO CLEAR 
INT20   OR   (HL) 
        LD   (HL),0 
        INC  HL 
        DJNZ INT20 
 \f

; 
; POSSIBLE CORRECTION FOR NEGATIVE NUMBERS 
; 
INT30   BIT  7,(IX)     ;  
        RET  Z; POSITIVE 
        AND  A 
        RET  Z          ; INPUT WAS AN INTEGER 
        LD   IY,C1 
        CALL SUB        ; SUBTRACT 1 TO CORRECT 
        RET 
; 
; X < 1, NONZERO:  OUTPUT 0 IF +, -1 IF - 
; 
INT40   BIT  7,(IX) 
        JP   Z,ZERO     ; POSITIVE FRACTION 
        CALL ONE 
        SET  7,(IX)     ; NEGATIVE 1 
        RET 
*H SHORT FUNCTIONS 
; 
; BRK SEPARATES INTEGER AND FRACTION PARTS 
; 
;   INPUT:  IX  PTS TO X 
;   OUTPUT: IX  PTS TO FRACTIONAL PART OF X (POSITIVE) 
;           HL  CONTAINS 2'S COMPL INTEGER PART OF X, 
;               LOW ORDER 16 BITS VALID IF X < 10 13 
;           CY  SET IF INTEGER WON'T FIT IN 16 BITS 
;           Z   SET IF EXACT INTEGER 
;           A'  IS ORIGINAL SIGN 
; 
BRK     LD   A,(IX)     ; GET SIGN 
        PUSH AF 
        CALL STO4       ; COPY X 
        CALL INT        ; TAKE INTEGER PART 
        LD   IY,TEMP4 
        CALL RSUB       ; CALC. FRACTION PART 
        PUSH IX         ; SAVE PTR 
        LD   IX,TEMP4 
        CALL FIXA       ; CALC. BINARY INTEGER PART 
        POP  IX 
        EX   AF,AF' 
        POP  AF         ; GET ORIGINAL SIGN 
        EX   AF,AF' 
        RET 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; ABSOLUTE VALUE FUNCTION 
;   INPUT,OUTPUT: IX POINTS TO FL PT NUMBER 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
ABS     RES  7,(IX)     ; TURN OFF SIGN BIT 
        RET 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; SIGN FUNCTION 
;   INPUT,OUTPUT.  IX POINTS TO FL PT NUMBER 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
SGN     XOR  A          ; CLEAR A 
        CP   (IX+7) 
 \f

        RET  Z          ; ZERO INPUT IS NOP 
        LD   A,(IX)     ; GET SIGN 
        AND  80H 
        CALL ONE        ; OUTPUT 1 
        OR   (IX) 
        LD   (IX),A     ; SIGN OF INPUT 
        RET 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; NEGATE FUNCTION 
;   INPUT,OUTPUT: IX POINTS TO FL PT NUMBER 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
NEG     LD   A,(IX)     ; GET SIGN BIT 
        XOR  80H        ; COMPLEMENT IT 
        LD   (IX),A     ; RESTORE 
        RET 
*H INTEGER ADD AND SUB 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; IADD, ISUB  INTEGER ADD AND SUBTRACT 
; 
;   INPUT:  IX  PTS TO X 
;           IY  PTS TO Y 
;   OUTPUT: IX  PTS TO SUM OR DIFFERENCE 
;   ERRORS: OVERFLOW (POSITIVE OR NEGATIVE) 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
IADD    CALL ASLOAD     ; LOAD ARGUMENTS 
        ADC  HL,DE 
        JP   PO,ASSTO   ; NO OVERFLOW 
ASOV    JP   P,NINF     ; OVFLW SIGN POS 
        JP   PINF 
ISUB    CALL ASLOAD     ; LOAD ARGUMENTS 
        SBC  HL,DE 
        JP   PO,ASSTO   ; NO OVERFLOW 
        JR   ASOV 
; 
; ASLOAD  LOADS ARGS TO HL, DE, RESETS CY 
; 
ASLOAD  LD   H,(IX+1) 
        LD   L,(IX) 
        LD   D,(IY+1) 
        LD   E,(IY) 
        AND  A 
        RET 
; 
; ASSTO  STORES HL AS RESULT 
; 
ASSTO   LD   (IX),L 
        LD   (IX+1),H 
        RET 
*H INTEGER MULTIPLY 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; IMUL  INTEGER MULTIPLY 
; 
;   INPUT:  IX  PTS TO X 
;           IY  PTS TO Y 
;   OUTPUT: IX  PTS TO PRODUCT 
;   ERRORS: OVERFLOW (POS OR NEG) 
 \f

;   REGISTERS:  DE IS MULTIPLICAND 
;               AC IS MULTIPLIER AND ACCUM EXTENSION 
;               HL IS ACCUM 
;               B  IS LOOP COUNTER 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
IMUL    CALL MDLOAD     ; LOAD ARGS 
        LD   A,B        ; X IN AC 
; 
; 16 BIT BY 16 BIT UNSIGNED MULTIPLY 
; 
        LD   HL,0       ; CLEAR ACCUM 
        LD   B,16       ; SET COUNTER 
        RRA             ; INITIALIZE CARRY 
        RR   C 
IM10    JR   NC,IM20    ; MPLIER BIT IS ZERO 
        ADD  HL,DE      ; ADD MULTIPLICAND 
IM20    RR   H          ; ROT ACC-MPLICAND INTO CY 
        RR   L 
        RRA 
        RR   C 
        DJNZ IM10       ; COUNTER NOT 0 
; 
; TEST FOR > 16 BIT PRODUCT 
; 
        LD   B,A        ; PRODUCT IN BC 
        LD   A,H 
        OR   L 
        JR   NZ,INF?    ; OVERFLOW 
; 
; TEST FOR >15 BITS, AND STORE RESULTS 
; 
MDSTO   EX   AF,AF'     ; GET SIGN OF RESULT 
        AND  80H 
        JR   Z,MDS20    ; POS RESULT 
; 
; NEGATE BC 
; 
        LD   HL,0 
        SBC  HL,BC 
        JR   Z,MDS10    ; RESULT WAS ZERO 
        JP   P,NINF     ; NEGATIVE OVERFLOW 
MDS10   LD   (IX),L     ; STORE RESULT 
        LD   (IX+1),H 
        RET 
; 
; TEST FOR > 15 BITS 
;  
MDS20   BIT  7,B 
        JR   NZ,PINF    ; POSITIVE OVERFLOW 
        LD   (IX),C 
        LD   (IX+1),B 
        RET 
; 
; INF? CHECKS SIGN BIT IN A' 
; PINF PRODUCES POS OVERFLOW 
; NINF PRODUCES NEG OVERFLOW 
; 
IDVO    LD   HL,ERROR 
        SET  4,(HL)     ; FLAG ERROR 
 \f

INF?    EX   AF,AF'     ; GET SIGN BIT 
        AND  80H 
        JR   NZ,NINF    ; NEG SIGN 
PINF    LD   (IX),0FFH  ; RESULT IS 7FFFH 
        LD   (IX+1),7FH 
        JR   FINF 
NINF    LD   (IX),0     ; RESULT IS 8000H 
        LD   (IX+1),80H 
FINF    LD   HL,ERROR 
        SET  6,(HL)     ; FLAG ERROR 
        RET 
*H INTEGER DIVIDE 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; IDIV  INTEGER DIVIDE 
; 
;   INPUT:  IX  PTS TO X 
;           IY  PTS TO Y 
;   OUTPUT: IX  PTS TO X/Y 
;   ERRORS: Y IS ZERO 
;   ALGORITHM: NON-RESTORING DIVISION, 16 BY 15 
;   REGISTERS:  AC IS DIVIDEND, ACCUM EXT 
;               DE IS DIVISOR 
;               HL IS ACCUM, REMAINDER AT END 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
IDIV    CALL MDLOAD     ; LOAD ARGS 
        LD   A,D 
        OR   E 
        JR   Z,IDV0     ; DIVISOR IS ZERO 
        LD   A,B        ; X IN AC 
; 
; 16 BIT BY 15 BIT UNSIGNED DIVIDE 
; 
        LD   HL,0       ; CLEAR ACCUM 
        LD   B,16       ; SET COUNTER 
IDV10                   ; 0 <= HL < DE 
        RL   C          ; ROT ACC-RESULT LEFT 
        RLA 
        ADC  HL,HL      ; NO CY POSSIBLE 
        SBC  HL,DE      ; SUB DIVISOR 
IDV20   CCF             ; CALC RESULT BIT 
        JR   NC,IDV50   ; ACCUM WENT NEGATIVE 
IDV30   DJNZ IDV10      ; COUNTER NOT 0 
        JP   IDV60 
IDV40                   ; DE <= HL < 0 
        RL   C          ; RO ACC-RESULT LEFT 
        RLA 
        ADC  HL,HL 
        AND  A          ; TURN OFF CY 
        ADC  HL,DE      ; ADD DIVISOR 
        JR   C,IDV30    ; ACCUM WENT POSITIVE 
        JR   Z,IDV20    ; ACCUM BECAME ZERO 
IDV50   DJNZ IDV40      ; COUNTER NOT 0 
IDV60   RL   C          ; SHIFT IN LAST RESULT BIT 
        RLA 
        LD   B,A        ; QUOTIENT IN BC 
        JP   MDSTO      ; STORE RESULT 
; 
; MDLOAD  LOADS X INTO BC, Y INTO DE 
;   TAKES ABS OF EACH, STORES XOR OF SIGNS 
;   IN A' \f

; 
MDLOAD  LD   B,(IX+1)   ; LOAD X 
        LD   C,(IX) 
        LD   A,B 
        AND  80H 
        JR   Z,MDL10    ; X IS POSITIVE 
; 
; NEGATE X 
; 
        LD   HL,0 
        SBC  HL,BC 
        LD   B,H 
        LD   C,L 
; 
; LOAD Y 
; 
MDL10   LD   D,(IY+1) 
        LD   E,(IY) 
        XOR  D          ; FORM SIGN OF RESULT 
        EX   AF,AF'     ; SAVE IT 
        BIT  7,D 
        RET  Z          ; Y IS POSITIVE 
; 
; NEGATE Y 
; 
        LD   HL,0 
        AND  A 
        SBC  HL,DE 
        EX   DE,HL 
        RET 
*H IABS AND ISGN 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; IABS, INEG 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
IABS    BIT  7,(IX+1) 
        RET  Z          ; X IS POSITIVE 
INEG    LD   D,(IX+1)   ; LOAD X 
        LD   E,(IX) 
        LD   HL,0       ; NEGATE X 
        AND  A 
        SBC  HL,DE 
        JP   PE,NINF    ; NEG OVERFLOW 
        LD   (IX+1),H   ; STORE X 
        LD   (IX),L 
        RET 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; ISGN 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
ISGN    LD   A,(IX+1)   ; GET SIGN 
        BIT  7,A 
        JR   Z,ISG10    ; X IS NONNEG 
        LD   (IX),0FFH  ; STORE -1 
        LD   (IX+1),0FFH 
        RET 
ISG10   OR   (IX) 
        RET  Z          ; X IS ZERO 
 \f

        LD   (IX+1),0   ; STORE +1 
        LD   (IX),1 
        RET 
*H ICP 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; ICP  INTEGER COMPARE 
; 
;   RETURNS CY SET IF X < Y 
;   RETURNS Z  SET IF X = Y 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
ICP     LD   B,(IX+1)   ; GET SIGN OF X 
        LD   A,B 
        AND  80H        ; TEST SIGN, CLEAR CY 
        JR   NZ,ICP10   ; X IS NEG 
        BIT  7,(IY+1) 
        RET  NZ         ; Y IS NEG 
        LD   A,B 
        CP   (IY+1)     ; SIGNS ARE BOTH POS 
        RET  NZ 
        LD   A,(IX) 
        CP   (IY) 
        RET 
ICP10   XOR  (IY+1)     ; TEST SIGN, CLEAR Z 
        RLA             ; SIGN BIT INTO CY 
        RET  C          ; SIGNS DIFFERENT 
        LD   A,B 
        CP   (IY+1)     ; BOTH SIGNS NEG 
        RET  NZ 
        LD   A,(IX) 
        CP   (IY) 
        RET 
; 
; REFERENCES 
; 
        EXTERNAL MULT,DIVI,ERROR,OVER,UNDER,SAVE 
        EXTERNAL        SEED,SEED10,CRNDA,CRNDC0 
        EXTERNAL        SRD,LD,MLDIG,MDTL 
        EXTERNAL        ZERO,ONE,NORML1,SLD,SUB,C1,MAD 
        EXTERNAL        STO4,TEMP4,RSUB,FIXA 
        EXTERNAL        LMARK,LREST,LBACK,RC2,LIN 
        GLOBAL  DTOB,BTOD 
        GLOBAL RND,RANDMZ,INT,BRK,ABS,SGN,NEG 
        GLOBAL IADD,ISUB,IMUL,IDIV,IABS,ISGN,ICP,INEG 
 \f

****************************************** 
DMATHM.S 
created  770914;  last modified  791023 
****************************************** 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; MISCELLANEOUS ROUTINES REQUIRED AS EXTERNALS FOR MATH PACKAGE 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
LMARK   LD   (POINT),HL ; STORE PTR FOR DTOB 
        RET 
LREST   RET             ; ENTRY FOR UNSUCCESSFUL DTOB (NO DIGITS FOUND) 
LBACK   RET             ; DUMMY ROUTINE (BACK UP PTR FOR BASIC) 
RC2     RET             ; NORMAL RETURN, IF SOME KIND OF NUMBER FOUND 
LIN     PUSH HL         ; SAVE HL 
        LD   HL,(POINT) ; GET PTR 
LIN10   LD   A,(HL)     ; GET NEXT CHAR 
        INC  HL         ; ADVANCE PTR 
        CP   ' ' 
        JR   Z,LIN10    ; IGNORE BLANKS 
        LD   (POINT),HL ; SAVE PTR 
        POP  HL         ; RESTORE HL 
        RET 
SCP     RET             ; STRING COMPARE 
POINT   DEFS 2          ; TEMP PTR STORAGE 
ERROR   DEFB 0          ; ERROR FLAGS FOR MATH PACKAGE 
ILLNUM  EQU  7          ; ILLEGAL NUMBER (DTOB) 
OVRFLW  EQU  6          ; OVERFLOW 
UNDFLW  EQU  5          ; UNDERFLOW 
DVDZRO  EQU  4          ; DIVISION BY ZERO 
SQRNGN  EQU  3          ; SQUARE ROOT OF NEGATIVE NUMBER 
LOGNGN  EQU  2          ; LOG OF NEGATIVE NUMBER 
; 
; REFERENCES 
; 
        GLOBAL          ERROR,SCP,LMARK,LREST,LBACK,RC2,LIN 
 \f

DVDIG   LD   HL,TEMP3   ; PT TO 8Y 
        CALL DVCP 
        JR   C,DVD10    ; AC1 < 8Y 
        LD   HL,TEMP30 
        CALL DVSUB      ; 8Y <= AC1 
DVD10   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP2   ; PT TO 4Y 
        CALL DVCP 
        JR   C,DVD20    ; AC1 < 4Y 
        LD   HL,TEMP20 
        CALL DVSUB      ; 4Y < AC1 
DVD20   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP1   ; PT TO 2Y 
        CALL DVCP 
        JR   C,DVD30    ; AC1 < 2Y 
        LD   HL,TEMP10 
        CALL DVSUB      ; 2Y < AC1 
DVD30   RL   C          ; COMPL RESULT BIT IN C 
        LD   HL,TEMP0   ; PT TO Y 
        CALL DVCP       ; COMPARE TO AC1 
        JR   C,DVD40    ; AC1 < Y 
        LD   HL,TEMP00   
        CALL DVSUB      ; Y < AC1 
DVD40   RL   C          ; COMPL RESULT BIT IN C 
        RET 
; 
; DVCP  ROUTINE TO COMPARE (DE) TO AC1 
;   RETURNS CY SET IFF (DE) < AC1 
;   RETURNS Z  SET IFF (DE) = AC1 
;   TIMING APPROX 42 
; 
DVCP    LD   DE,AC1     ; PT TO AC1 
        LD   B,7        ; SET COUNTER 
DVC10   LD   A,(DE)     ; GET BYTE 
        CP   (HL) 
        RET  NZ         ; < OR > 
        INC  HL         ; INC PTRS 
        INC  DE 
        DJNZ DVC10      ; COUNTER NOT 0 
        RET 
;  
; DVSUB  ROUTINE TO SUBTRACT (DE) FROM AC1 
;   ASSUMES 14 DIGIT OPERANDS 
;   TIMING 376 
; 
DVSUB   LD   DE,AC10    ; PT TO ACCUM 
        AND  A          ; CLEAR CY 
        LD   B,7 
DV40    LD   A,(DE) 
        SBC  A,(HL) 
        DAA 
        LD   (DE),A 
        DEC  DE 
        DEC  HL 
        DJNZ DV40 
        RET 
; 
; ROUTINE TO LOAD TEMP REGISTERS 
;   TIMING 2014 
; 
 \f

MDTL    LD   DE,TEMP0   ; FIRST DEST 
        CALL MOV        ; LOAD TEMP0 
        LD   HL,TEMP0   ; PT TO SRC 
        RES  7,(HL)     ; CLEAR SIGN BIT 
        LD   B,3        ; SET COUNTER 
; 
; LOOP TO COPY TEMPN TO TEMPN+1 & SHFT LFT 1 BIT 
; 
MDTL1   LD   A,B        ; SAVE COUNTER 
        CALL MOV        ; MOVE TO NEXT TEMP 
        LD   B,A        ; RESTORE COUNTER 
        AND  A          ; CLEAR CY 
        CALL SLB1       ; SHFT LEFT (HL ALREADY OK) 
        INC  HL         ; PT TO MSBYTE JUST SHIFTED 
        DJNZ MDTL1      ; COUNTER NOT 0 
        RET 
; 
; DETERMINE OVER OR UNDER 
; 
MERR    JP   P,UNDER    ; UNDERFLOW 
        JP   OVERA 
; 
; DIVISION BY ZERO ERROR 
; 
DIV0    LD   HL,ERROR 
        SET  4,(HL) 
        JP   INF 
*H FIX 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; FIX CONVERTS FLOATING POINT NUMBER TO 
;        16 BIT 2'S COMPLEMENT INTEGER 
;        (ROUNDING) 
; 
;   INPUT:  IX  PTS TO FL PT NUMBER 
;   OUTPUT: IX  PTS TO INTEGER 
;   ERRORS:  OVERFLOW IF X > 32767 OR X < -32768 
; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
FIX     LD   IY,C _5 
        CALL ADD         ; ADD .5 
        CALL FIXA        ; CONVERT NUMBER 
        JR   NC,FX10     ; NO OVERFLOW 
        LD   HL,ERROR 
        SET  6,(HL)      ; FLAG OVERFLOW 
        LD   HL,7FFFH    ; 32767 
        BIT  7,(IX) 
        JR   Z,FX10      ; POSITIVE SIGN 
        LD   HL,8000H    ; -32768 
FX10    LD   (IX),L      ; STORE INTEGER 
        LD   (IX+1),H 
        RET 
; 
; MAIN CONVERSION FOR FIX 
; 
;   RETURNS CY SET IF OVERFLOW 
;   RETURNS Z  SET IF EXACT INTEGER 
;   HL IS LOW 16 BITS OF INT(X) FOR ALL X < 10 13 
; 
 \f

\f

«eof»