home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / forth / compiler / fpc / source / sfloat3.seq < prev    next >
Text File  |  1989-08-25  |  41KB  |  1,249 lines

  1. \ SFLOAT3 - Floating Point Extensions
  2. \
  3. \ CR CR  .( Copyright 1988 by R. L. Smith )  CR
  4. \        .( Version 2.00-A )  CR
  5. \
  6. \
  7. \
  8. \               (c) Copyright 1988 by Robert L. Smith
  9. \                       2300 St Francis Dr.
  10. \                       Palo Alto, CA 94303
  11. \                          (415)856-9321
  12. \
  13. \       Permission is granted to use this package or its derivatives for
  14. \       private use.  For permission to use it in programs or packages
  15. \       sold for profit, please contact the author.
  16. \
  17.  
  18. DEFINED NOFLOATING NIP #IF NOFLOATING #THEN
  19.  
  20. ANEW FEXPSRC
  21. \ LOADED,
  22. PREFIX
  23. HEX
  24. ALSO HIDDEN DEFINITIONS
  25.  
  26. CREATE 1GEXPTAB
  27.  
  28.         \ Table of (1 - e^(k/16))  for k <= 0
  29.         3FFE , FE8C , DC02 ,  3FFE , EDF2 , 36CB ,  3FFE , DC45 , 6CF4 ,
  30.         3FFE , C974 , D039 ,  3FFE , B56D , 8E6D ,  3FFE , A01B , 9EA1 ,
  31.         3FFE , 8969 , AD21 ,  3FFD , E282 , 0C2A ,  3FFD , AF12 , FDA8 ,
  32.         3FFC , F0A5 , 76C5 ,  3FFB , F82A , 021C ,  0000 , 0000 , 0000 ,
  33.  
  34.         \ Table of (e^(k/16) - 1)  for k >= 0
  35.         3FFC , 8415 , ABBF ,  3FFD , 8858 , 116E ,  3FFD , D32E , 05C3 ,
  36.         3FFE , 916B , C788 ,  3FFE , BBD2 , 2EC1 ,  3FFE , E8F4 , A27B ,
  37.         3FFF , 8C80 , 2478 ,  3FFF , A612 , 98E2 ,  3FFF , C14B , 4312 ,
  38.         3FFF , DE45 , 5DF8 ,  3FFF , FD1D , E618 ,
  39.  
  40. 42 1GEXPTAB + CONSTANT GEXPTAB    \ Points to zero point of table.
  41.  
  42. LABEL Y**2                      \ Argument in (BX,CX)
  43.         CLEAR_LABELS
  44.                                 \ Start calculation of y^2
  45.         MOV     AX, BX
  46.         MUL     CX              \ A*B
  47.         XCHG    AX, CX          \ ABL -> CX
  48.         MOV     AL, AH
  49.         MUL     AL              \ B^2  (note 8 bit multiply)
  50.         SHR     AX
  51.         ADD     CX, AX
  52.         ADC     DX, # 0         \ AB + (B^2)/2
  53.         XCHG    DX, BX          \ A -> DX,  AB -> (BX,CX)
  54.         MOV     AX, DX
  55.         MUL     AX              \ A^2
  56.         SHL     CX              \ 2AB + B^2
  57.         RCL     BX
  58.         ADC     DX, # 0
  59.         ADD     BX, AX
  60.         ADC     DX, # 0
  61.         SHL     CX              \ Round
  62.         ADC     BX, # 0
  63.         ADC     DX, # 0
  64.         MOV     CX, BX
  65.         MOV     BX, DX          \ y^2 -> (BX,CX)
  66.         RET
  67.         END-CODE
  68.  
  69. LABEL FRACT*
  70. \ 32 bit by 32 bit multiply.  Let  (DI,BP) = (A,B), and (BX,CX) = (C,D)
  71.         MOV     AX, BP
  72.         MUL     CX              \ B*D
  73.         MOV     AX, CX          \ D
  74.         MOV     CX, DX          \ BDhi
  75.         MUL     DI              \ A*D
  76.         ADD     CX, AX          \ BDhi + ADlo
  77.         ADC     DX, # 0         \ ADhi + carry1 , no carry out in this case.
  78.         XCHG    DX, BP          \ B -> DX,  ADhi -> BP
  79.         MOV     AX, BX          \ C
  80.         MUL     DX              \ B*C
  81.         ADD     CX, AX          \ BDhi + ADlo + BClo
  82.         ADC     BP, # 0         \ ADhi + carry1 + carry2
  83.         MOV     AX, DI          \ A
  84.         XCHG    BX, DX          \ BChi -> CX, C -> DX
  85.         MUL     DX              \ A*C
  86.         ADD     BX, AX          \ BChi + AClo
  87.         ADC     DX, # 0         \ AChi + carry
  88.         ADD     BX, BP          \ BChi + AClo + ADhi + previous carries.
  89.         ADC     DX, # 0         \ AChi + carry -> Product high part.
  90.         RET                     \ Product in (DX,BX)
  91.         END-CODE
  92.  
  93. LABEL GEXP1-                     \ Negative argument case
  94.         CLEAR_LABELS
  95. \ On entry, y = x*2^4 = (BX,CX), x = (SI,(SP)), x*(2/45) in (DX,AX)
  96.         MOV     BP, # 4444
  97.         SUB     BP, AX
  98.         MOV     AX, # 4444      \ 4/15
  99.         SBB     AX, DX          \ ((4/15) - (2/45)*x)
  100.         MUL     SI              \ * x
  101.         MOV     BP, # 5555
  102.         MOV     DI, # 5555
  103.         SUB     DI, AX
  104.         SBB     BP, DX          \ (1/3) - x * ((4/15) - (2/45)*x)
  105.         MOV     DX, BP          \ Note an implied addition by 1
  106.         MOV     AX, DI          \ 17 bit multiply
  107.         SHR     DI
  108.         OR      BH, BH
  109.         JS      1 $
  110.         ADD     DI, AX
  111. 1 $:    RCR     DI
  112.         MOV     AX, BX          \ yhi
  113.         MUL     DX              \ * y
  114.         ADD     AX, DI
  115.         ADC     DX, # 0
  116.         XOR     DI, DI
  117.         ADD     AX, CX          \ + y
  118.         ADC     DX, BX          \ Product in (DI,DX,AX)
  119.         ADC     DI, # 0
  120.         MOV     BP, # 5555
  121.         MOV     AX, # 0055
  122.         SUB     BP, DX
  123.         SBB     AX, DI          \ ((1/3)*(2^-8) - y*(2^-16)*prev
  124.         MOV     DI, AX
  125.         CALL    Y**2
  126.         CALL    FRACT*
  127.         POP     AX              \ xlo
  128.         SUB     AX, BX
  129.         SBB     SI, DX          \ x - prev
  130.         SHR     SI              \ Shift right by 1
  131.         RCR     AX
  132.         ADC     AX, # 0         \ Round
  133.         ADC     SI, # 0
  134.         NOT     SI              \ Subtract from 1 by negating result.
  135.         NEG     AX
  136.         CMC
  137.         ADC     SI, # 0
  138.         MOV     DX, SI
  139.         POP     SI              \ Restore SI and BP
  140.         POP     BP
  141.         MOV     BX, FSP
  142.         MOV     4 [BX], AX      \ Push result
  143.         MOV     2 [BX], DX
  144.         MOV     AX, # 3FFF      \ Exponent of result.
  145.         MOV     0 [BX], AX
  146.         NEXT
  147.         END-CODE
  148.  
  149. CODE GEXP1   ( F: r1 -- r2 )  \  |f1| < 2^-4  \  GEXP1 = (exp(r1) - r1) / r1 .
  150.         CLEAR_LABELS
  151.         MOV     BX, FSP
  152.         MOV     CX, 0 [BX]      \ Sign and biased exponent.
  153.         MOV     DX, 4 [BX]      \ LS part of r1
  154.         MOV     BX, 2 [BX]      \ MS part of r1
  155.         MOV     DI, CX          \ Save sign
  156.         AND     CX, # 7FFF      \ Mask off sign bit
  157.         SUB     CX, # 3FFB      \ Get unbiased exponent + 4
  158.         CMP     CX, # -8
  159.         JG      3 $
  160.         CMP     CX, # -20
  161.         JG      1 $
  162.         XOR     AX, AX          \ Unbiased exponent <= -36
  163.         MOV     DX, # 4000
  164.         MOV     CX, # 8000
  165.         MOV     BX, FSP
  166.         MOV     4 [BX], AX
  167.         MOV     2 [BX], CX
  168.         MOV     0 [BX], DX
  169.         NEXT
  170.  
  171. 1 $:    CMP     CX, # -10
  172.         JG      2 $
  173.         MOV     DX, BX          \ Shift right by 16
  174.         XOR     BX, BX
  175.         ADD     CX, # 10        \ Adjust exponent
  176. 2 $:    CMP     CX, # -8
  177.         JG      3 $
  178.         MOV     DL, DH          \ Shift right by 8.
  179.         MOV     DH, BL
  180.         MOV     BL, BH
  181.         XOR     BH, BH
  182.         ADD     CX, # 8
  183. 3 $:    PUSH    BP
  184.         PUSH    SI
  185.         OR      CX, CX
  186.         JZ      5 $
  187.         NEG     CX
  188. 4 $:    SHR     BX
  189.         RCR     DX
  190.         LOOP    4 $
  191.         ADC     DX, # 0         \ Round
  192.         ADC     BX, # 0
  193. 5 $:    MOV     CX, DX          \ y = x*(2^4) in (BX,CX)
  194.         MOV     SI, BX
  195.         SHR     SI              \ Shift right by 4.
  196.         RCR     DX
  197.         SHR     SI
  198.         RCR     DX
  199.         SHR     SI
  200.         RCR     DX
  201.         SHR     SI
  202.         RCR     DX
  203.         ADC     DX, # 0
  204.         ADC     SI, # 0         \ Round
  205.         PUSH    DX              \ x in (SI,(SP))
  206.         MOV     AX, # 0B61      \ 2/45
  207.         MUL     SI              \ * x
  208.         OR      DI, DI
  209.         JNS     6 $             \ Jump if r1 is positive.
  210.         JMP     GEXP1-          \ Jump to negative case.
  211. 6 $:    ADD     AX, # 4444
  212.         ADC     DX, # 4444      \ + 4/15
  213.         MOV     AX, SI
  214.         MUL     DX              \ * x
  215.         ADD     AX, # 5555
  216.         ADC     DX, # 5555      \ + 1/3, double, implied 1+
  217.         MOV     DI, AX          \ Perform a 17 bit multiply.
  218.         SHR     DI
  219.         OR      BH, BH
  220.         JNS     7 $
  221.         ADD     DI, AX
  222. 7 $:    RCR     DI
  223.         MOV     AX, BX          \ yhi
  224.         MUL     DX              \ * y
  225.         ADD     AX, DI
  226.         ADC     DX, # 0
  227.         XOR     DI, DI
  228.         ADD     AX, CX
  229.         ADC     DX, BX
  230.         ADC     DI, # 0
  231.         ADD     DX, # 5555
  232.         ADC     DI, # 0055      \ + (1/3)*2^-8
  233.         MOV     BP, DX
  234.         CALL    Y**2
  235.         CALL    FRACT*
  236.         POP     AX              \ xlo
  237.         ADD     AX, BX
  238.         ADC     DX, SI          \ + x
  239.         SHR     DX              \ Shift right by 2
  240.         RCR     AX
  241.         SHR     DX
  242.         RCR     AX
  243.         ADC     AX, # 0         \ Round
  244.         ADC     DX, # 8000      \ + 1
  245.         POP     SI              \ Restore SI and BP
  246.         POP     BP
  247.         MOV     BX, FSP
  248.         MOV     4 [BX], AX      \ Push result
  249.         MOV     2 [BX], DX
  250.         MOV     CX, # 4000      \ Exponent of result.
  251.         MOV     0 [BX], CX
  252.         NEXT
  253.         END-CODE
  254.  
  255. PREVIOUS DEFINITIONS
  256.  
  257. CODE FNORMALIZE   ( F: r1 -- r2 )
  258.         CLEAR_LABELS
  259.         MOV     BX, FSP
  260.         MOV     CX, 0 [BX]      \ SX1
  261.         MOV     AX, 2 [BX]      \ FH1
  262.         OR      AX, AX          \ Check if already normalized
  263.         JS      3 $             \ If so, just return.
  264.         JNZ     4 $             \ If high part non-zero, shift less than 16
  265.         MOV     AX, 4 [BX]      \ FL1  Shift left by 16 by waving a hand.
  266.         XOR     DX, DX
  267.         OR      AX, AX          \ Check if argument is all zero.
  268.         JZ      2 $
  269.         SUB     CX, # 10        \ Reduce exponent to compensate.
  270.         JO      1 $             \ Jump if we underflowed
  271.         OR      AX, AX
  272.         JS      7 $
  273.         JMP     5 $
  274.  
  275. 1 $:    XOR     AX, AX          \ Underflow case.  Set results to 0.
  276.         MOV     4 [BX], AX
  277.         MOV     2 [BX], AX
  278. 2 $:    MOV     0 [BX], AX
  279. 3 $:    NEXT
  280.  
  281. 4 $:    MOV     DX, 4 [BX]
  282. 5 $:    OR      AH, AH
  283.         JNZ     6 $
  284.         SUB     CX, # 8
  285.         MOV     AH, AL
  286.         MOV     AL, DH
  287.         XOR     DL, DL
  288.         OR      AH, AH
  289.         JS      7 $
  290. 6 $:    DEC     CX
  291.         SHL     DX
  292.         RCL     AX
  293.         JNO     6 $
  294. 7 $:    MOV     4 [BX], DX
  295.         MOV     2 [BX], AX
  296.         MOV     0 [BX], CX
  297.         NEXT
  298.  
  299.         END-CODE
  300.  
  301. CODE >INTFRACT   ( F: r1 -- ur2 ; -- int )   \ r2 may not be normalized.
  302.         CLEAR_LABELS
  303.         MOV     BX, FSP
  304.         MOV     AX, 0 [BX]      \ Sign + exponent
  305.         MOV     DX, 4 [BX]      \ LS part
  306.         MOV     BX, 2 [BX]      \ MS part
  307.         XOR     DI, DI          \ Integer part
  308.         MOV     CX, AX
  309.         AND     CX, # 7FFF      \ Strip sign from exponent
  310.         SUB     CX, # 3FFF      \ Calculate true exponent
  311.         JLE     2 $             \ Jump if no shifting required
  312. 1 $:    SHL     DX              \ Left shift loop
  313.         RCL     BX
  314.         RCL     DI
  315.         LOOP    1 $
  316.         OR      AX, # 3FFF      \ Set resultant exponent to 3FFF
  317.         AND     AX, # BFFF      \ But keep sign.
  318.         JNS     2 $             \ Jump if positive sign
  319.         NEG     DI              \ Otherwise negate integer part
  320. 2 $:    PUSH    DI
  321.         MOV     CX, BX
  322.         MOV     BX, FSP
  323.         MOV     4 [BX], DX      \ Push fractional part of real
  324.         MOV     2 [BX], CX
  325.         OR      DX, CX
  326.         JZ      3 $             \ Jump if fractional part is zero
  327.         MOV     0 [BX], AX      \ Else push exponent and integer part
  328.         NEXT                    \ And exit
  329.  
  330. 3 $:    MOV     0 [BX], CX      \ If fractional part is zero, push 0 exponent
  331.         NEXT
  332.         END-CODE
  333.  
  334. : FLOOR   ( F: r -- ; -- n )
  335.         >INTFRACT FPOP DUP
  336.         IF    0<
  337.               IF    2DROP 1-
  338.               ELSE  2DROP
  339.               THEN
  340.         ELSE  DROP 2DROP
  341.         THEN ;
  342.  
  343. : CEILING   ( F: r -- ; -- n )
  344.         >INTFRACT FPOP DUP
  345.         IF    0< 0=
  346.               IF    2DROP 1+
  347.               ELSE  2DROP
  348.         THEN
  349.         ELSE  DROP 2DROP
  350.         THEN ;
  351.  
  352. ALSO HIDDEN DEFINITIONS
  353.  
  354. : GEXPTAB@   ( F: -- r ; n -- )
  355.         6 * GEXPTAB + F@ ;
  356.  
  357. : AUX-    ( F: r1 -- r2 ; n -- )
  358.         ?DUP
  359.         IF   GEXPTAB@ FOVER F1.0+ F* F-   THEN ;
  360.  
  361. : AUX+    ( F: r1 -- r2 ; n -- )
  362.         ?DUP
  363.         IF   GEXPTAB@ FOVER FOVER F* F+ F+  THEN ;
  364.  
  365. : GEXP0   ( F: r1 -- r2 ; -- n )
  366.         4 FSP @ +!
  367.         >INTFRACT -4 FSP @ +!
  368.         FNORMALIZE FDUP GEXP1 F* ;
  369.  
  370. : GEXPLN2   ( F: r1 -- r2 ; -- n )
  371.         FNORMALIZE FLN2 F* GEXP0 ;
  372.  
  373. PREVIOUS DEFINITIONS
  374.  
  375. : FEXP    ( F: r1 -- r2 )
  376.         [ ALSO HIDDEN ]
  377.         FPSEXP 0<
  378.         IF      FDUP FLN2 FNEGATE F<=
  379.                 IF      F/LN2 FPSEXP BFF2 <
  380.                         IF      FDROP F0.0 EXIT   THEN
  381.                         >INTFRACT GEXPLN2 AUX- F1.0+ FSP @ +!
  382.                 ELSE    GEXP0 AUX- F1.0+
  383.                 THEN
  384.         ELSE    FDUP FLN2 F>=
  385.                 IF      F/LN2 FPSEXP 400D >
  386.                         IF      FDROP -1 -1 7FFF FPUSH
  387.                                 [ LAST @ NAME> ] LITERAL 10 FPERR EXIT
  388.                         ELSE    >INTFRACT GEXPLN2 AUX+ F1.0+ FSP @ +!
  389.                         THEN
  390.                 ELSE    GEXP0 AUX+ F1.0+
  391.                 THEN
  392.         THEN ;
  393.  
  394. PREVIOUS
  395.  
  396. : FALN   ( F: r1 -- r2 )   FEXP ;
  397.  
  398. : F**    ( F: r1 r2 -- r3 )
  399.         FSWAP FLN F* FEXP ;
  400.  
  401. : FALOG   ( F: r1 -- r2 )
  402.         FLN10.0 F* FEXP ;
  403.  
  404. ALSO HIDDEN DEFINITIONS
  405.  
  406. : F2**   ( F: -- r ; n -- )
  407.         >R 0 8000 4000 R> + FPUSH ;
  408.  
  409. : F2**N-1   ( F: -- r ; n -- )
  410.         F2** F1.0 F- ;
  411.  
  412. : FEXP-1    ( F: r1 -- r2 )                \ ( e^x - 1 )
  413.         FPSEXP 0<
  414.         IF      FDUP FLN2 FNEGATE F<=
  415.                 IF      F/LN2 FPSEXP BFF2 <
  416.                         IF      FDROP F1.0 EXIT   THEN
  417.                         >INTFRACT GEXPLN2 AUX- DUP FSP @ +!
  418.                         F2**N-1 F+
  419.                 ELSE    GEXP0 AUX-
  420.                 THEN
  421.         ELSE    FDUP FLN2 F>=
  422.                 IF      F/LN2 FPSEXP 400D >
  423.                         IF      FDROP -1 -1 7FFF FPUSH
  424.                                 [ LAST @ NAME> ] LITERAL 10 FPERR EXIT
  425.                         ELSE    >INTFRACT GEXPLN2
  426.                                 AUX+ DUP FSP @ +!
  427.                                 F2**N-1 F+
  428.                         THEN
  429.                 ELSE    GEXP0 AUX+
  430.                 THEN
  431.         THEN ;
  432.  
  433. : FSINH1   ( F: r1 -- r2 )
  434.         FEXP-1 FDUP FDUP F1.0+ F/ F+ -1 FSP @ +! ;
  435.  
  436. : FTANH1   ( F: r1 -- r2 )
  437.         1 FSP @ +!
  438.         FEXP-1 FDUP 0 8000 4001 FPUSH F+ F/ ;
  439.  
  440. PREVIOUS DEFINITIONS
  441.  
  442. : FSINH    ( F: r1 -- r2 )
  443.         [ ALSO HIDDEN ]
  444.         FPSEXP 0<
  445.         IF   FNEGATE FSINH1 FNEGATE
  446.         ELSE FSINH1
  447.         THEN ;
  448.         PREVIOUS
  449.  
  450. : FCOSH   ( F: r1 -- r2 )
  451.         FABS FEXP F1.0 FOVER F/ F+ -1 FSP @ +! ;
  452.  
  453. : FTANH   ( F: r1 -- r2 )
  454.         [ ALSO HIDDEN ]
  455.         FPSEXP 0<
  456.         IF   FTANH1
  457.         ELSE FNEGATE FTANH1 FNEGATE
  458.         THEN ;
  459.         PREVIOUS
  460.  
  461. HEX
  462.  
  463. F900 9502 4021 FPUSH FCONSTANT F1.0E10
  464.  
  465. \ : ISCALE    ( n ilg -- ilg len iscale )
  466. \        SWAP DUP 0<
  467. \        IF    NEGATE OVER 0 MAX +  THEN
  468. \        0A MIN 1 MAX
  469. \        2DUP SWAP - ;
  470.  
  471. : T#     ( t1 -- t2)     \ Output one digit of a triple number.
  472.         0 BASE @ UM/MOD >R
  473.         BASE @ UM/MOD >R
  474.         BASE @ UM/MOD
  475.         SWAP 0 # 2DROP R> R> ;
  476.  
  477. : TDUP0=   ( t -- t flag )
  478.         2DUP OR 3 PICK OR 0= ;
  479.  
  480. : FPARTS    ( F: r -- ; n -- t exp sign )       \ t is a triple number.
  481.         0A MIN 1 MAX                            \ Limit range of width.
  482.         FDUP0=                                  \ Check for 0.0
  483.         IF   FDROP DROP 0 0 0 0 0  EXIT THEN    \ Handle 0.0
  484.         FPSEXP 0< 2* 1+ >R                      \ Save Sign.
  485.         FABS FDUP FLOG FLOOR 1+                 \ Get output exponent.
  486.         2DUP -                                  \ Scaling power
  487.         F10.0 F**N*                             \ Scale the number
  488.         F0.5 F+ FINT                            \ Round the result (add 0.5)
  489.         SWAP FDUP F10.0 F**N F< 0=              \ Compare with 10^n
  490.         IF   F10.0 F/ 1+   THEN                 \ If too large, divide by 10
  491.         >R TINTA R> R> ;
  492.  
  493. DECIMAL
  494. : (E.)   ( F: r -- ; n -- addr cnt )
  495.         FPARTS                                  \ Separate into pieces.
  496.         BASE @ >R >R                            \ Save current base, sign
  497.         DUP -99 <                               \ Check for very small exp.
  498.         IF  2DROP 2DROP 0 0 0 0  THEN           \ If small, use zero.
  499.         DUP 99 >                                \ Check for large exponent.
  500.         IF  BELL EMIT  THEN                     \ Error is just a bell!
  501.         DECIMAL  <#                             \ Begin numeric formatting.
  502.         DUP ABS 0 # #S 2DROP 0<                 \ Output exp.
  503.         IF  ASCII -  ELSE ASCII +  THEN HOLD    \ Output sign of exp.
  504.         ASCII E HOLD                            \ Output the "E".
  505.         10 0 DO  T#  LOOP DROP                  \ Output remaining digits
  506.         ASCII . HOLD                            \ Output the decimal point
  507.         R> 0<                                   \ Check sign
  508.         IF   ASCII -  ELSE   BL  THEN   HOLD    \ Output sign
  509.         R> BASE ! #> ;                          \ Restore base and exit.
  510.  
  511. : E.   ( F: r -- )    10 (E.) TYPE SPACE ;
  512.  
  513. : E.R    ( F: r -- ; places width -- )
  514.         SWAP 1 MAX 10 MIN SWAP
  515.         OVER - SPACES (E.) TYPE ;
  516.  
  517. CREATE F#PLACES    10 ,
  518.  
  519. : PLACES   ( n -- )
  520.         0 MAX 10 MIN F#PLACES ! ;
  521.  
  522. ALSO HIDDEN DEFINITIONS
  523.  
  524. : (F.FRACT)   ( F: r -- ; #pl -- )
  525.         >R <# TINTA R> 1 MAX 0
  526.         DO  T#  LOOP
  527.         DROP 2DROP ASCII . HOLD ;
  528.  
  529. : (F.INT1)    ( F: r -- ; sign -- addr cnt )
  530.         TINTA
  531.         BEGIN DUP WHILE T# REPEAT DROP
  532.         2DUP OR  IF #S THEN
  533.         ROT  IF   ASCII - HOLD  THEN
  534.         #> ;
  535.  
  536. : HOLDBL   ( n -- )
  537.         DUP 0 >
  538.         IF    0 DO  BL HOLD  LOOP
  539.         ELSE  DROP  THEN ;
  540.  
  541. : (F.INT2)    ( F: r1 r2 --    ; sign width -- addr cnt 0 )
  542.               ( F: r1 r2 -- r1 ; sign width -- addr cnt -1 )
  543.         >R TINTA -1 0 R> 1-
  544.         DO    DROP T# TDUP0=  IF I LEAVE  THEN  -1
  545.         -1 +LOOP
  546.         >R DROP 2DROP 0<  IF  ASCII - HOLD  THEN
  547.         R> DUP 0<
  548.         IF    0 #> -1
  549.         ELSE  HOLDBL  0 0 #> 0 FDROP
  550.         THEN ;
  551.  
  552. : (F.INTR)    ( F: r1 r2 --    ; width #pl sign -- addr cnt 0  )
  553.               ( F: r1 r2 -- r1 ; width #pl sign -- addr cnt -1 ) \ Error case
  554.         DUP >R - 1+ - R> SWAP DUP 0<            \ ( sign width' flag )
  555.         IF     FDROP #> -1 EXIT  THEN
  556.         ?DUP 0=
  557.         IF    TINTA OR OR
  558.               IF     0 #> -1 EXIT
  559.               ELSE   0<  IF ASCII - HOLD  THEN
  560.                      0 0 #> FDROP 0 EXIT
  561.               THEN
  562.         THEN  (F.INT2) ;
  563.  
  564. HEX
  565.  
  566. : (F.1)    ( F: r1 -- r2 r3 ; #pl -- sign #pl flag )
  567.         FPSEXP 0< SWAP FABS FPSEXP 7F00 >
  568.         IF      F0.0 FSWAP -1 EXIT  THEN
  569.         F10.0 DUP
  570.         F**N FSWAP FOVER F* F0.5 F+ FINT
  571.         FSWAP F/PREM FPSEXP 4021 > ;
  572.  
  573. PREVIOUS DEFINITIONS
  574.  
  575. : F.     ( F: r -- )
  576.         F#PLACES @ 1 MAX 0A MIN
  577.         FDUP0=
  578.         IF      FDROP F0.0  THEN
  579.         [ ALSO HIDDEN ] (F.1)
  580.         IF      DROP FNIP [ LAST @ NAME> ] LITERAL 40 FPERR
  581.                 IF   FNEGATE  THEN 0A (E.)
  582.         ELSE    FSWAP (F.FRACT) (F.INT1)
  583.         THEN    TYPE SPACE ;  PREVIOUS
  584.  
  585. : F.R    ( F: r -- ; #pl width -- )
  586.         [ ALSO HIDDEN ] FDUP SWAP DUP (F.1)
  587.         IF      DROP F2DROP [ LAST @ NAME> ] LITERAL 40 FPERR
  588.                 IF   FNEGATE  THEN 0A (E.)
  589.         ELSE    FSWAP (F.FRACT)         \ ( F: r1 r2 -- ; width #pl sign )
  590.                 (F.INTR)
  591.                 IF    2DROP [ LAST @ NAME> ] LITERAL 40 FPERR 0A (E.)
  592.                 THEN  TYPE
  593.         THEN ;  PREVIOUS
  594.  
  595. : ?FSTACK   ( F: -- )       \ Check Floating Point stack.
  596.         (?STACK) FDEPTHB DUP 0<
  597.         IF      FCLEAR DROP TRUE ABORT" Floating Point Stack Underflow"
  598.         THEN
  599.         [ ALSO HIDDEN ] FPSSIZE >=
  600.         IF      FCLEAR TRUE ABORT" Floating Point Stack Overflow"
  601.         THEN ;
  602.         PREVIOUS
  603.  
  604. DECIMAL
  605. : .FS   ( F: -- )
  606.         ?FSTACK CR
  607.         FDEPTHB DUP 0=
  608.         IF      ." {0} "  DROP
  609.         ELSE
  610.               DUP 6 / <# 32 HOLD ASCII } HOLD 0 #S ASCII { HOLD #> TYPE
  611.               1+ DUP 19 - 6 MAX
  612.               DO      FSP0 I - F@ E.
  613.               6 +LOOP
  614.         THEN ;
  615. HEX
  616.  
  617. : UNPACK   ( F: r -- ; -- d n )
  618.         FDUP0=                                  \ Check for 0.0
  619.         IF   FDROP 0 0 0 FPUSH EXIT  THEN       \ Handle 0.0
  620.         FPSEXP FABS FDUP FLOG FLOOR 1+ >R       \ Save Sign, output exp.
  621.         09 R@ - F10.0 F**N*                     \ Scale the number
  622.         F0.5 F+ FINT                            \ Round the result
  623.         FDUP 2800 EE6B 401D FPUSH ( 10^9 )
  624.         F< 0=                                   \ Compare with 10^9
  625.         IF   F10.0 F/ R> 1+                     \ If too large, divide by 10
  626.         ELSE R>
  627.         THEN
  628.         SWAP 0<
  629.         IF   FNEGATE  THEN
  630.         >R INT R> 9 - ;
  631.  
  632. : FASINH   ( F: r1 -- r2 )
  633.         FDUP FABS F1.0 F>
  634.         IF      F1.0 FOVER F/ FDUP F* F1.0 F+ FSQRT FOVER F*
  635.         ELSE    FDUP FDUP F* F1.0 F+ FSQRT
  636.         THEN
  637.         F+ FLN ;
  638.  
  639. : FACOSH   ( F: r1 -- r2 )
  640.         FDUP FABS F1.0 F<
  641.         IF      FDROP F0.0 [ LAST @ NAME> ] LITERAL 10 FPERR
  642.         ELSE    F1.0 FOVER FDUP F* F- FSQRT F+ FLN
  643.         THEN ;
  644.  
  645. : FATANH   ( F: r1 -- r2 )
  646.         FDUP FABS F1.0 F<
  647.         IF      F1.0 FOVER F+ FSWAP F1.0 F- F/ FLN 1 -
  648.         ELSE
  649.                 FPSEXP FDROP FINFINITY 0<
  650.                 IF    FNEGATE  THEN
  651.                 [ LAST @ NAME> ] LITERAL 10 FPERR
  652.         THEN ;
  653.  
  654. CODE UMT*   ( ut1 n -- ut2 )      \ Multiply a triple number by a single.
  655.         POP     DI
  656.         POP     CX
  657.         POP     BX
  658.         POP     AX
  659.         MUL     DI
  660.         PUSH    AX              \ Lowest part of result.
  661.         MOV     AX, BX
  662.         MOV     BX, DX
  663.         MUL     DI
  664.         ADD     BX, AX
  665.         ADC     DX, # 0
  666.         PUSH    BX              \ Middle part of product.
  667.         MOV     BX, DX
  668.         MOV     AX, CX
  669.         MUL     DI
  670.         ADD     AX, BX
  671.         PUSH    AX              \ Most significant part of product.
  672.         NEXT
  673.         END-CODE
  674.  
  675. CODE TS+   ( ut1 n -- ut2 )
  676.         POP     AX
  677.         POP     BX
  678.         POP     CX
  679.         POP     DX
  680.         ADD     DX, AX
  681.         ADC     CX, # 0
  682.         ADC     BX, # 0
  683.         PUSH    DX
  684.         PUSH    CX
  685.         PUSH    BX
  686.         NEXT
  687.         END-CODE
  688.  
  689. : TCONVERT   ( ut1 adr1 -- ut2 adr2 )
  690.         BEGIN   1+ DUP >R C@ BASE @ DIGIT
  691.         WHILE
  692.                 OVER 1000 U<        \ Check for very large numbers
  693.                 IF
  694.                         >R BASE @ UMT* R> TS+
  695.                         DOUBLE?  IF DPL INCR  THEN
  696.                 ELSE    DROP
  697.                 THEN  R>
  698.         REPEAT  DROP R> ;
  699.  
  700. CODE TFLOAT   ( F: -- r ; ut -- )   \ Float triple precision unsigned number
  701.         CLEAR_LABELS
  702.         POP     AX              \ MS part
  703.         POP     BX              \ Mid part
  704.         POP     DX              \ LS part
  705.         MOV     CX, # 402F      \ Initial exponent.
  706.         OR      AX, AX          \ See if we can shift 16 bits at a time.
  707.         JNZ     1 $
  708.         SUB     CX, # 10        \ Yes.  Adjust exponent.
  709.         MOV     AX, BX          \ Shift left by 16 bits
  710.         MOV     BX, DX
  711.         XOR     DX, DX          \ Zero out LS part.
  712.         OR      AX, AX          \ Can we shift another 16 bits?
  713.         JNZ     1 $
  714.         SUB     CX, # 10        \ Adjust exponent again
  715.         MOV     AX, BX          \ Shift left another 16 bits
  716.         XOR     BX, BX          \ Clear middle part
  717.         OR      AX, AX          \ Check for initial value of 0.
  718.         JZ      9 $
  719. 1 $:    OR      AH, AH          \ See if we can shift by 8 bits
  720.         JNZ     2 $
  721.         SUB     CX, # 8         \ Yes.
  722.         MOV     AH, AL
  723.         MOV     AL, BH
  724.         MOV     BH, BL
  725.         MOV     BL, DH
  726.         MOV     DH, DL
  727.         XOR     DL, DL
  728.         OR      AH, AH          \ Test MS bit
  729. 2 $:    JS      4 $
  730. 3 $:    DEC     CX              \ MS bit not set, so shift left by 1
  731.         SHL     DX, # 1
  732.         RCL     BX, # 1
  733.         RCL     AX, # 1
  734.         JNO     3 $             \ Overflow indicates MS bit set.
  735. 4 $:    ADD     DX, # 8000      \ Begin rounding process
  736.         JC      6 $             \ Jump if rounding needed.
  737. 5 $:    MOV     DI, BX
  738.         MOV     BX, FSP
  739.         SUB     BX, # 6
  740.         MOV     FSP BX
  741.         MOV     4 [BX], DI      \ Push result on floating point stack.
  742.         MOV     2 [BX], AX
  743.         MOV     0 [BX], CX
  744.         NEXT
  745.  
  746. 6 $:    JZ      8 $             \ Rounding.  Jump for round to even case.
  747.         ADC     BX, # 0
  748.         ADC     AX, # 0
  749.         JNC     5 $             \ Jump if no carry out
  750. 7 $:    RCR     AX, # 1         \ Shift right
  751.         RCR     BX, # 1
  752.         INC     CX              \ Adjust exponent
  753.         JMP     5 $
  754.  
  755. 8 $:    ADC     BX, # 0
  756.         ADC     AX, # 0
  757.         JC      7 $
  758.         AND     BX, # FFFE
  759.         JMP     5 $
  760.  
  761. 9 $:    MOV     BX, FSP
  762.         SUB     BX, # 6
  763.         MOV     FSP BX
  764.         MOV     4 [BX], AX      \ Zero result
  765.         MOV     2 [BX], AX
  766.         MOV     0 [BX], AX
  767.         NEXT
  768.         END-CODE
  769.  
  770. VARIABLE FPT  0 FPT !
  771.  
  772. VARIABLE FLTS   0 FLTS !
  773.  
  774. : FLOATS   ( -- )               \ Allows decimal point to mean floating #.
  775.         -1 FLTS ! ;
  776.  
  777. : DOUBLES   ( -- )              \ Decimal point in number means double.
  778.         0 FLTS ! ;
  779.  
  780. : PACK   ( F: -- r ; d n -- )
  781. \ Convert a double integer and power of 10 to a floating point number.
  782.         >R FLOAT R> F10.0 F**N* ;
  783.  
  784. : -NUMBER   ( adr1 -- adr2 flag )
  785.         DUP 1+ C@ ASCII - = DUP >R - R> ;
  786.  
  787. : 1FNUMBER   ( F: -- r ; ut adr -- -1 )   \ if convertable
  788.                       \ or  ( ut adr -- 0 ) if not convertable.
  789.         DPL @ FPT !  >R 0 0 R> -NUMBER  >R  DPL -1!  CONVERT
  790.         DUP C@ BL <>
  791.         IF      DUP C@ 29 = SWAP 1+ C@ BL = AND 0=
  792.         ELSE    DROP 0
  793.         THEN
  794.         OR DOUBLE? OR
  795.         FPT @ DPL !  FPT 0!
  796.         IF      DROP R> DROP 2DROP DROP 0  EXIT  THEN
  797.         R>  IF  NEGATE  THEN
  798.         FPT -1!  DOUBLE?
  799.         IF   DPL @ -  THEN
  800.         >R TFLOAT BASE @ IFLOAT R> F**N* TRUE ;
  801.  
  802. \ ( F: -- r ; adr -- -1)   \ if convertable into floating point
  803. \ (adr -- d 1 ) \ ( adr -- 0 )
  804.  
  805.  
  806. : (FNUMBER?)  \ ( F: -- r ; adr -- 1)   \ if convertable into floating point
  807.               \ ( adr -- d -1 ) / ( adr -- 0 )
  808.         >R 0 0 0 R> -NUMBER >R
  809.         DPL -1!  FPT 0!
  810.         BEGIN   TCONVERT DUP C@ ASCII . =
  811.         WHILE   DPL 0!
  812.         REPEAT
  813.         DUP C@ BL =
  814.         IF      DROP DPL @ 0> FLTS @ AND
  815.                 IF      TFLOAT F10.0 DPL @ NEGATE F**N* R>
  816.                         IF  FNEGATE THEN        1       \ TRUE  \ 07/06/89 TJZ
  817.                 ELSE    DROP R>
  818.                         IF   DNEGATE  THEN      TRUE    \ 1     \ 07/06/89 TJZ
  819.                 THEN    EXIT
  820.         THEN
  821.         DUP C@ DUP 28 = SWAP 0DF AND 45 = OR
  822.         IF      1FNUMBER
  823.                 IF      R>  IF   FNEGATE  THEN  1       \ TRUE  \ 07/06/89 TJZ
  824.                 ELSE    R> DROP                 FALSE
  825.                 THEN
  826.         ELSE    R> 2DROP ( 2DROP ) drop         FALSE           \ 08/25/89 TJZ
  827.         THEN ;
  828.  
  829. \ 07/06/89 19:47:10.34 TJZ REMOVED FOLLOWING DEFINITION
  830. \ : (FNUMBER??)   ( A1 --- D1 )           \ Prefix with $ for auto HEX base.
  831. \         +1=$?                     \ $ is for HEX
  832. \         IF
  833. \         ELSE    +1='?                   \ recognize ' for ascii
  834. \                 IF      2+ C@ 0 TRUE
  835. \                         DPL ON
  836. \                 ELSE    (FNUMBER?)
  837. \                 THEN
  838. \         THEN    ;
  839.  
  840. : FNUMBER   ( F: -- r ; adr -- -1 )     \ if convertable.
  841.                 \ ( adr -- d 1 ) \ Error message
  842. \        (FNUMBER??) DUP 0= ?MISSING  ; \ 07/06/89 19:47:26.60 TJZ CHANGE
  843.                 %NUMBER dup 0= ?MISSING ;
  844.  
  845. : F#   ( F: -- r ; fnumber --- )
  846.         BL WORD FNUMBER 0> 0=   \ 0< 0=                         \ 07/06/89 TJZ
  847.         IF      DUP 0<
  848.                 IF      DABS 0 TFLOAT FNEGATE
  849.                 ELSE    0 TFLOAT
  850.                 THEN
  851.                 DPL @ 0>
  852.                 IF      DPL @ NEGATE F10.0 F**N*
  853.                 THEN
  854.         THEN ;
  855.  
  856. : #?    ( number --- val flag )
  857.         BL WORD FNUMBER NEGATE ;        \  07/06/89 TJZ NEGATE ADDED
  858.  
  859. CODE (FLIT)   ( F: -- r )
  860.         MOV     BX, FSP
  861.         SUB     BX, # 6
  862.         MOV     FSP BX
  863.         LODSW   ES:
  864.         MOV     0 [BX], AX
  865.         LODSW   ES:
  866.         MOV     2 [BX], AX
  867.         LODSW   ES:
  868.         MOV     4 [BX], AX
  869.         NEXT
  870.         END-CODE
  871.  
  872. : FLITERAL    ( F: r -- )
  873.         COMPILE (FLIT) FPOP X, X, X, ;  IMMEDIATE
  874.  
  875. \ Add to Status line in Floating Point mode.
  876.  
  877. DECIMAL
  878. ALSO HIDDEN DEFINITIONS
  879.  
  880. : <.FSTAT>   ( -- )
  881.         #OUT @ #LINE @ >R >R  ATTRIB C@ >R  BASE @ >R
  882.         DECIMAL 74 0 AT FDEPTHB 6 / DUP
  883.         IF      >ATTRIB4 ."  {" (U.) TYPE ." }" 2 SPACES >ATTRIB1
  884.         ELSE    >ATTRIB1 DROP ."  {0}  "
  885.         THEN
  886.         R> BASE ! R> ATTRIB C! R> R> AT ;
  887.  
  888. PREVIOUS DEFINITIONS
  889.  
  890. : .FSTATUS   ( -- )
  891.         [ HIDDEN ALSO ]
  892.         DEFERS STATUS
  893.         ?STACK STATV @
  894.         IF   <.FSTAT>   THEN ;
  895. PREVIOUS
  896. HEX
  897.  
  898. : FINTERP       ( -- )
  899.         BEGIN   ?FSTACK  DEFINED
  900.                 IF      EXECUTE
  901.                 ELSE    FNUMBER -1 =    \ 1 =                   \ 07/06/89 TJZ
  902.                         IF      DOUBLE? NOT IF DROP THEN  THEN
  903.                 THEN    FALSE DONE?
  904.         UNTIL   ;
  905.  
  906. : (F])          ( -- )
  907.         STATE ON
  908.         BEGIN   ?FSTACK DEFINED DUP
  909.                 IF      0> IF  EXECUTE  ELSE  X,  THEN
  910.                 ELSE    DROP FNUMBER -1 = \ 1 =                 \ 07/06/89 TJZ
  911.                         IF      DOUBLE?
  912.                                 IF   [COMPILE] DLITERAL
  913.                                 ELSE DROP [COMPILE] LITERAL
  914.                                 THEN
  915.                         ELSE    [COMPILE] FLITERAL
  916.                         THEN
  917.                 THEN
  918.                 TRUE DONE?
  919.         UNTIL ;
  920.  
  921. ALSO HIDDEN DEFINITIONS
  922.  
  923. DEFER OLD-INTERP
  924. DEFER OLD-]
  925. DEFER OLD-?STACK
  926. DEFER OLD-STATUS
  927. DEFER OLD-LOADSTAT
  928. DEFER OLD-#NUM          \ 07/06/89 19:46:21.35 TJZ ADDED
  929.  
  930. PREVIOUS DEFINITIONS
  931.  
  932. : FLOATING      ( -- )
  933.         [ ALSO HIDDEN ] \ 07/06/89 19:46:32.77 TJZ ADDED FOLLOWING TWO LINES
  934.         @> #NUM      IS OLD-#NUM           ['] (FNUMBER?) IS #NUM
  935.         @> INTERPRET IS OLD-INTERP         ['] FINTERP    IS INTERPRET
  936.         @> ]         IS OLD-]              ['] (F])       IS ]
  937.         @> ?STACK    IS OLD-?STACK         ['] ?FSTACK    IS ?STACK
  938.         @> STATUS    IS OLD-STATUS         ['] .FSTATUS   IS STATUS
  939.         @> LOADSTAT  IS OLD-LOADSTAT       ['] <.FSTAT>   IS LOADSTAT ;
  940.         PREVIOUS
  941.  
  942. : NOFLOATING    ( -- )
  943.         [ ALSO HIDDEN ] \ 07/06/89 19:46:46.23 TJZ ADDED FOLLOWING TWO LINES
  944.         @> OLD-#NUM     IS #NUM
  945.         @> OLD-INTERP   IS INTERPRET
  946.         @> OLD-]        IS ]
  947.         @> OLD-?STACK   IS ?STACK
  948.         @> OLD-STATUS   IS STATUS
  949.         @> OLD-LOADSTAT IS LOADSTAT ;
  950.         PREVIOUS
  951.  
  952. ALSO HIDDEN DEFINITIONS
  953. CODE AUXTAN  ( F: r1 -- ur2 )       \ ur2 is tan(x) - x , |x| < 2^-4
  954.         CLEAR_LABELS
  955.         MOV     BX, FSP
  956.         MOV     CX, 0 [BX]      \ Sign and biased exponent.
  957.         MOV     DX, 4 [BX]      \ LS part of r1
  958.         MOV     BX, 2 [BX]      \ MS part of r1
  959.         MOV     DI, CX          \ Save sign
  960.         AND     DI, # 8000
  961.         ADD     DI, # 3FF2      \ Generate Sign and Exponent of result.
  962.         AND     CX, # 7FFF      \ Mask off sign bit
  963.         SUB     CX, # 3FFB      \ Get unbiased exponent + 4
  964.         PUSH    BP
  965.         PUSH    SI
  966.         PUSH    DI
  967.         CMP     CX, # -8
  968.         JG      3 $
  969.         CMP     CX, # -10
  970.         JG      2 $
  971.         XOR     CX, CX
  972.         ADD     SP, # 6         \ Don't bother popping the stack.
  973.         MOV     BX, FSP
  974.         MOV     4 [BX], CX
  975.         MOV     2 [BX], CX
  976.         MOV     0 [BX], CX
  977.         NEXT
  978.  
  979. 2 $:    MOV     AH, DL          \ Shift right by 8
  980.         MOV     DL, DH
  981.         MOV     DH, BL
  982.         MOV     BL, BH
  983.         XOR     BH, BH
  984.         ADD     CX, # 8
  985.         JNZ     3 $             \ Jump if we need more shifting
  986.         ADD     AH, # 80
  987.         JMP     5 $
  988.  
  989. 3 $:    OR      CX, CX
  990.         JZ      6 $
  991.         NEG     CX
  992. 4 $:    SHR     BX
  993.         RCR     DX
  994.         LOOP    4 $
  995. 5 $:    ADC     DX, # 0         \ Round
  996.         ADC     BX, # 0
  997. 6 $:    MOV     CX, DX          \ y = x*(2^4) in (BX,CX)
  998.         MOV     SI, BX
  999.         PUSH    DX              \ y in (SI,(SP))
  1000.         CALL    Y**2            \ y^2 in (BX,CX)
  1001.         MOV     AL, # 37        \ 68/315
  1002.         MUL     BH              \ (y^2)*(2^-8)*(68/315)
  1003.         MOV     AL, AH
  1004.         XOR     AH, AH
  1005.         ADD     AX, # 8889      \ + (8/15)
  1006.         MUL     BX              \ * (y^2)
  1007.         MOV     AL, AH          \ Shift right by 8
  1008.         MOV     AH, DL
  1009.         MOV     DL, DH
  1010.         XOR     DH, DH
  1011.         SHR     DX              \ /2
  1012.         RCR     AX
  1013.         ADD     AX, # AAAB      \ + (2/3)
  1014.         ADC     DX, # AAAA
  1015.         MOV     BP, AX
  1016.         MOV     DI, DX          \ Partial result in (DI,BP)
  1017.         CALL    FRACT*          \ *(y^2).  Result in (DX,BX)
  1018.         MOV     DI, DX
  1019.         MOV     BP, BX
  1020.         MOV     BX, SI
  1021.         POP     CX
  1022.         CALL    FRACT*          \ *y.  Result in (DX,BX)
  1023.         POP     AX              \ SX
  1024.         POP     SI
  1025.         POP     BP
  1026.         MOV     DI, BX
  1027.         MOV     BX, FSP
  1028.         MOV     4 [BX], DI
  1029.         MOV     2 [BX], DX
  1030.         MOV     0 [BX], AX
  1031.         NEXT
  1032.         END-CODE
  1033.  
  1034. CREATE TANTAB           \ Table of tan(i/16)  for i = 0 to 12.
  1035.         0000 , 0000 , 0000 ,   3FFC , 802A , BBC3 ,   3FFD , 80AB , BD79 ,
  1036.         3FFD , C248 , 3789 ,   3FFE , 82BC , 2D22 ,   3FFE , A56B , 8F6B ,
  1037.         3FFE , C989 , 6C2D ,   3FFE , EF7A , 4F55 ,   3FFF , 8BDA , 7AE0 ,
  1038.         3FFF , A164 , 5D07 ,   3FFF , B8B3 , 344F ,   3FFF , D236 , 595F ,
  1039.         3FFF , EE7D , 1B09 ,
  1040.  
  1041. : GTAN0   ( F: r1 -- r2 r3 )       \ The tangent is the ratio of r2 to r3.
  1042.         4 FSP @ +!
  1043.         >INTFRACT 6 * TANTAB + >R
  1044.         -4 FSP @ +!
  1045.         FNORMALIZE FDUP AUXTAN FNORMALIZE F+ FDUP R@ F@ F+
  1046.         FSWAP R> F@ F* F1.0 F\- ;
  1047.  
  1048. : GTAN1   ( F: r1 -- r2 r3 ; flag )
  1049.         PI -2 FSP @ +!  ( pi/4)
  1050.         F/PREM FPOP 401F =
  1051.         IF    DROP >R FNORMALIZE GTAN0 R@ 1 AND
  1052.               IF    FOVER FOVER R> 2 AND
  1053.                     IF    F- F-ROT F+
  1054.                     ELSE  F+ F-ROT F\-
  1055.                     THEN
  1056.               ELSE  R> 2 AND
  1057.                     IF    FNEGATE FSWAP  THEN
  1058.               THEN 0
  1059.         ELSE  2DROP -1
  1060.         THEN ;
  1061.  
  1062. : GTAN2   ( F: r1 -- r2 r3 ; -- flag1 flag2 )
  1063.         \ flag1 is non-zero if out of range.  flag2 is non-zero if r3 = 0.
  1064.         FDUP0<  ( FDUP F0< )
  1065.         IF      FNEGATE GTAN1 FNEGATE
  1066.         ELSE    GTAN1
  1067.         THEN
  1068.         FDUP0= ;
  1069.  
  1070. PREVIOUS DEFINITIONS
  1071.  
  1072. : FTAN   ( F: r1 -- r2 )
  1073.         [ ALSO HIDDEN ] GTAN2
  1074.         IF      FDROP F0<
  1075.                 IF      -1 -1 C0FF ( Default -infinity )
  1076.                 ELSE    -1 -1 40FF ( Default infinity )
  1077.                 THEN    FPUSH
  1078.         ELSE    F/
  1079.         THEN
  1080.         IF      [ LAST @ NAME> ] LITERAL 10 FPERR
  1081.         THEN ;
  1082.         PREVIOUS
  1083.  
  1084. : FSIN   ( F: r1 -- r2 )
  1085.         [ ALSO HIDDEN ]
  1086.         -1 FSP @ +!  ( 2.0E0 F/ ) GTAN2
  1087.         IF      FDROP FDROP F0.0
  1088.         ELSE    F/ FDUP FDUP F* F1.0 F+ F/ 1 FSP @ +! ( 2.0E0 F* )
  1089.         THEN
  1090.         IF      [ LAST @ NAME> ] LITERAL 10 FPERR
  1091.         THEN ;
  1092.         PREVIOUS
  1093.  
  1094. : FCOS   ( F: r1 -- r2 )
  1095.         [ ALSO HIDDEN ]
  1096.         -1 FSP @ +! ( 2.0E0 F/ ) GTAN2
  1097.         IF      FDROP FDROP F1.0 FNEGATE
  1098.         ELSE    FOVER FOVER FOVER FOVER
  1099.                 F\- F-ROT F+ F*
  1100.                 F-ROT FDUP F* FSWAP FDUP F* F+ F/
  1101.         THEN
  1102.         IF      [ LAST @ NAME> ] LITERAL 10 FPERR
  1103.         THEN ;
  1104.         PREVIOUS DEFINITIONS
  1105.  
  1106. ALSO HIDDEN DEFINITIONS
  1107. CODE AUXATAN  ( F: r1 -- ur2 )     \ ur2 is x - arctan(x) , |x| < 2^-4
  1108.         CLEAR_LABELS
  1109.         MOV     BX, FSP
  1110.         MOV     CX, 0 [BX]      \ Sign and biased exponent.
  1111.         MOV     DX, 4 [BX]      \ LS part of r1
  1112.         MOV     BX, 2 [BX]      \ MS part of r1
  1113.         MOV     DI, CX          \ Save sign
  1114.         AND     DI, # 8000
  1115.         ADD     DI, # 3FF2      \ Generate Sign and Exponent of result.
  1116.         AND     CX, # 7FFF      \ Mask off sign bit
  1117.         SUB     CX, # 3FFB      \ Get unbiased exponent + 4
  1118.         PUSH    BP
  1119.         PUSH    SI
  1120.         PUSH    DI
  1121.         CMP     CX, # -8
  1122.         JG      3 $
  1123.         CMP     CX, # -10
  1124.         JG      2 $
  1125.         XOR     CX, CX
  1126.         ADD     SP, # 6         \ Don't bother popping the stack.
  1127.         MOV     BX, FSP
  1128.         MOV     4 [BX], CX
  1129.         MOV     2 [BX], CX
  1130.         MOV     0 [BX], CX
  1131.         NEXT
  1132.  
  1133. 2 $:    MOV     AH, DL          \ Shift right by 8
  1134.         MOV     DL, DH
  1135.         MOV     DH, BL
  1136.         MOV     BL, BH
  1137.         XOR     BH, BH
  1138.         ADD     CX, # 8
  1139.         JNZ     3 $             \ Jump if we need more shifting
  1140.         ADD     AH, # 80
  1141.         JMP     5 $
  1142.  
  1143. 3 $:    OR      CX, CX
  1144.         JZ      6 $
  1145.         NEG     CX
  1146. 4 $:    SHR     BX
  1147.         RCR     DX
  1148.         LOOP    4 $
  1149. 5 $:    ADC     DX, # 0         \ Round
  1150.         ADC     BX, # 0
  1151. 6 $:    MOV     CX, DX          \ y = x*(2^4) in (BX,CX)
  1152.         MOV     SI, BX
  1153.         PUSH    DX              \ y in (SI,(SP))
  1154.         CALL    Y**2            \ y^2 in (BX,CX)
  1155.         MOV     AL, # 92        \ 4/7
  1156.         MUL     BH              \ (y^2)*(2^-8)*(4/7)
  1157.         MOV     AL, AH
  1158.         XOR     AH, AH
  1159.         NEG     AX
  1160.         ADD     AX, # CCCD      \ + (4/5)
  1161.         MUL     BX              \ * (y^2)
  1162.         MOV     AL, AH          \ Shift right by 8
  1163.         MOV     AH, DL
  1164.         MOV     DL, DH
  1165.         XOR     DH, DH
  1166.         SHR     DX              \ /2
  1167.         RCR     AX
  1168.         ADC     AX, # 0         \ Round
  1169.         ADC     DX, # 0
  1170.         NEG     DX              \ Negate
  1171.         NEG     AX
  1172.         SBB     DX, # 0
  1173.         ADD     AX, # AAAB      \ + (2/3)
  1174.         ADC     DX, # AAAA
  1175.         MOV     BP, AX
  1176.         MOV     DI, DX          \ Partial result in (DI,BP)
  1177.         CALL    FRACT*          \ *(y^2).  Result in (DX,BX)
  1178.         MOV     DI, DX
  1179.         MOV     BP, BX
  1180.         MOV     BX, SI
  1181.         POP     CX
  1182.         CALL    FRACT*          \ *y.  Result in (DX,BX)
  1183.         POP     AX              \ SX
  1184.         POP     SI
  1185.         POP     BP
  1186.         MOV     DI, BX
  1187.         MOV     BX, FSP
  1188.         MOV     4 [BX], DI
  1189.         MOV     2 [BX], DX
  1190.         MOV     0 [BX], AX
  1191.         NEXT
  1192.         END-CODE
  1193.  
  1194. \ arctangent table
  1195. CREATE ATANTAB          \ Table of arctan (k/16), for k = 0 to 16.
  1196.      0000 , 0000 , 0000 ,    3FFB , FFAA , DDB9 ,    3FFC , FEAD , D4D5 ,
  1197.      3FFD , BDCB , DA5E ,    3FFD , FADB , AFC9 ,    3FFE , 9B13 , B9B8 ,
  1198.      3FFE , B7B0 , CA0F ,    3FFE , D327 , 761E ,    3FFE , ED63 , 382B ,
  1199.      3FFF , 832B , F4A7 ,    3FFF , 8F00 , 5D5F ,    3FFF , 9A2F , 80E6 ,
  1200.      3FFF , A4BC , 7D19 ,    3FFF , AEAC , 4C39 ,    3FFF , B805 , 3E2C ,
  1201.      3FFF , C0CE , 85B9 ,    3FFF , C90F , DAA2 ,
  1202.  
  1203. : GATAN1   ( F: r1 -- r2 )         \ 0 <= r1 <= 1.0
  1204.         FDUP 4 FSP @ +! >INTFRACT DUP
  1205.         IF    >R -4 FSP @ +!
  1206.               FNORMALIZE FSWAP R@ IFLOAT -4 FSP @ +!
  1207.               F* F1.0 F+ F/ FDUP AUXATAN FNORMALIZE F- R>
  1208.               6 * ATANTAB + F@ F+
  1209.         ELSE  DROP -4 FSP @ +!
  1210.               FNORMALIZE FDUP AUXATAN FNORMALIZE F- FNIP
  1211.         THEN ;
  1212.  
  1213. : GATAN2   ( F: r1 -- r2 )         \ 0 <= r1
  1214.         FPSEXP 4000 <
  1215.         IF      GATAN1
  1216.         ELSE    F1.0 FSWAP F/ GATAN1 FNEGATE PI -1 FSP @ +! ( F2.0 F/ ) F+
  1217.         THEN ;
  1218.  
  1219. PREVIOUS DEFINITIONS
  1220.  
  1221. : FATAN   ( F: r1 -- r2 )          \ arctangent routine
  1222.         [ ALSO HIDDEN ]
  1223.         FDUP0<
  1224.         IF      FNEGATE GATAN2 FNEGATE
  1225.         ELSE    GATAN2
  1226.         THEN ;
  1227.         PREVIOUS
  1228.  
  1229. : FASIN   ( F: r1 -- r2 )          \ arcsine routine
  1230.         FDUP FABS F1.0 F>
  1231.         IF      [ LAST @ NAME> ] LITERAL 10 FPERR
  1232.         ELSE    FDUP F1.0 F+ FOVER FNEGATE F1.0 F+ F* FSQRT F/
  1233.                 FATAN
  1234.         THEN ;
  1235.  
  1236. : FACOS   ( F: r1 -- r2 )          \ arccosine routine
  1237.         FDUP FABS F1.0 F>
  1238.         IF      [ LAST @ NAME> ] LITERAL 10 FPERR
  1239.         ELSE    F1.0 FOVER F- FSWAP F1.0 F+ F/ FSQRT FATAN 1 FSP @ +!
  1240.         THEN ;
  1241.  
  1242. : FTRIG0   ( F: r1 -- r2 )         \ SQRT ( ABS ( 1 - X^2 ))
  1243.         FDUP F* F- FABS FSQRT ;
  1244.  
  1245. FLOATING
  1246. DECIMAL
  1247.  
  1248.  
  1249.