\ Reference: zenfloat.arc and rtfv5.pdf on taygeta
\ Martin Tracy's Zenfloat - apparently released to public domain
\ in the 1984 Forml proceedings
\ A commented version found in Tim Hendtlass's "Real Time Forth"
\ Physics Department, Swinburne University of Technology, Australia.
\ See: rtfv5.pdf on taygeta ftp server.
\ Reformated here with code from zenforth.arc for comparison.
\ Only changes are the use of the constant zfsize instead of using 6553.
\ Converted to 4tH by David Johnson, 2009-05-18
\ Several fixes by Hans Bezemer and David Johnson
[UNDEFINED] F+ [IF]
[UNDEFINED] UM* [IF] include lib/mixed.4th [THEN]
/cell 4 [=] [IF] 214748364 ( 429496729/2 ) constant zfsize [THEN]
/cell 2 [=] [IF] 3276 ( 6553/2 ) constant zfsize [THEN]
0 constant S>F
: D10* d2* 2dup d2* d2* d+ ;
: D+- 0< if dnegate then ;
: TRIM ( dn n -- f)
>r \ exponent to return stack
tuck dabs \ save sign, make double positive
begin
over 0< over 0<> or \ MSB low word set
while \ or top 16 bits not=0?
0 10 um/mod >r \ divide by 10
10 um/mod nip r> r> 1+ >r \ and increase exponent
repeat
rot d+- drop r> \ apply sign and final exponent
;
: F+ ( f1 f2 -- f3 )
rot 2dup - dup 0< \ work out difference in exponents
if \ top number has the larger exponent
negate rot >r nip >r swap r> \ keep larger and diff, swap mantissas
else \ top has a smaller or equal exponent
swap >r nip \ keep larger (on RS) and diff
then \ convert larger to double, top >r
>r dup abs u>d rot d+- r> dup 0
?do
>r d10* r> 1- \ mantissa * 10, decrement exponent
over abs zfsize > \ would another *10 cause overflow?
if leave then \ prematurely terminate loop if so
loop
r> over + >r \ calculate final exponent
if rot drop \ top were +ve lose bottom
else rot dup abs u>d rot d+- d+
then r> trim \ top were -ve, make double and add on
; \ get final exponent and trim
: FNEGATE >r negate r> ;
: F- fnegate f+ ; \ add negative of the top value
: FABS over 0< if fnegate then ; \ negate if negative
: F>S dup 0< if abs 0 ?do 10 / loop else 0 ?do 10 * loop then ;
\ loop until exponent is zero
: F* ( f1 f2 -- f3 )
rot + >r \ calc exp of answer,save on RS
2dup xor >r \ save xor of mantissa (sign of answer)
abs swap abs um* \ make mantissas positive and multiply
r> d+- r> trim \ apply sign and get exponent and trim
;
: F/ ( f1 f2 -- f3 )
over 0= abort" Divide by zero" \ first check and check if 2OS is zero
2>r over 0= 2r> rot if 2drop exit then
rot swap - >r \ get exponent of answer, put on RS
2dup xor -rot \ get sign of answer, tuck down on DS
abs dup zfsize min rot abs u>d \ make number +ve, divisor < 6553
begin \ would divisor * 10 be < dividend?
2dup d10* nip >r >r over r> r> rot u<
while d10* r> 1- >r \ yes, divisor * 10, 1- answer exp
repeat
2swap drop um/mod \ now do the division
nip 0 rot d+- r> trim \ lose rem apply sign get exp & trim
;
\ print an FP number in fixed format
: F. ( f --)
over 0= if dup xor then \ fix zero
>r dup abs s>d \ save exponent
<# r@ 0 max 0 ?do [char] 0 hold loop
r@ 0< if \ save any trailing zeros needed
r@ negate 0 max 0 ?do # loop [char] . hold
then \ generate actual number
r> drop #s sign #> type space \ and print the whole number
;
: F0= drop 0= ; ( f -- bool)
: F0< drop 0< ; ( f -- bool)
: F< F- F0< ; ( f1 f2 -- bool)
: F= F- F0= ; ( f1 f2 -- bool)
false [IF]
\ Check zfsize
cr ." zfsize is " zfsize . ." compared to " -1 1 um* 10 um/mod nip 2 / . cr
cr ." i 1/i i+0.123456789"
15 1 do cr i 2 .r space 1 S>F i S>F f/ f. space 123456789 -9 i S>F f+ f. loop
CR
CR .( Basic arithmetic ------------)
CR .( 1/7 = ) 1 S>F 7 S>F F/ F.
CR .( 1/3 = ) 1 S>F 3 S>F F/ F.
CR .( 2/3 = ) 2 S>F 3 S>F F/ F.
CR .( 355/113 = ) 355 S>F 113 S>F F/ F.
CR .( 123 + 456 = ) 123 S>F 456 S>F F+ F.
CR .( 123 - 456 = ) 123 S>F 456 S>F F- F.
CR .( 456 - 123 = ) 456 S>F 123 S>F F- F.
CR .( Basic comparison ------------)
CR .( 0 F0= ) 0 S>F F0= .
CR .( -1 F0= ) -1 S>F F0= .
CR .( 1 F0= ) 1 S>F F0= .
CR .( 0 F0< ) 1 S>F F0< .
CR .( -1 F0< ) -1 S>F F0< .
CR .( 1 F0< ) 1 S>F F0< .
[THEN]
[DEFINED] 4TH# [IF]
hide zfsize
hide d10*
hide d+-
hide trim
[THEN]
[THEN]
|