Plan 9 from Bell Labs’s /usr/web/sources/contrib/fgb/root/sys/src/cmd/4th/lib/zenfloat.4th

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


\ 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]

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].