File:  [gforth] / gforth / float.fs
Revision 1.57: download - view: text, annotated - select for diffs
Mon Mar 22 17:08:06 2010 UTC (9 years, 6 months ago) by anton
Branches: MAIN
CVS tags: HEAD
added ARM disassembler (contributed by Andreas Bolka)
some fixes in the ARM assembler (contributed by Andreas Bolka)
ARM assembler and disassembler are now distributed
FCOPYSIGN now works with the strangely ordered floats on ARM

    1: \ High level floating point                            14jan94py
    2: 
    3: \ Copyright (C) 1995,1997,2003,2004,2005,2006,2007,2009 Free Software Foundation, Inc.
    4: 
    5: \ This file is part of Gforth.
    6: 
    7: \ Gforth is free software; you can redistribute it and/or
    8: \ modify it under the terms of the GNU General Public License
    9: \ as published by the Free Software Foundation, either version 3
   10: \ of the License, or (at your option) any later version.
   11: 
   12: \ This program is distributed in the hope that it will be useful,
   13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
   14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15: \ GNU General Public License for more details.
   16: 
   17: \ You should have received a copy of the GNU General Public License
   18: \ along with this program. If not, see http://www.gnu.org/licenses/.
   19: 
   20: \ 1 cells 4 = [IF]
   21: \ ' cells   Alias sfloats
   22: \ ' cell+   Alias sfloat+
   23: \ ' align   Alias sfalign
   24: \ ' aligned Alias sfaligned
   25: \ [ELSE]
   26: \ : sfloats  2* 2* ;
   27: \ : sfloat+  4 + ;
   28: \ : sfaligned ( addr -- addr' )  3 + -4 and ;
   29: \ : sfalign ( -- )  here dup sfaligned swap ?DO  bl c,  LOOP ;
   30: \ [THEN]
   31: 
   32: \ 1 floats 8 = [IF]
   33: \ ' floats   Alias dfloats
   34: \ ' float+   Alias dfloat+
   35: \ ' falign   Alias dfalign
   36: \ ' faligned Alias dfaligned
   37: \ [ELSE]
   38: \ : dfloats  2* 2* 2* ;
   39: \ : dfloat+  8 + ;
   40: \ : dfaligned ( addr -- addr' )  7 + -8 and ;
   41: \ : dfalign ( -- )  here dup dfaligned swap ?DO  bl c,  LOOP ;
   42: \ [THEN]
   43: 
   44: : sfalign ( -- ) \ float-ext s-f-align
   45:     \G If the data-space pointer is not single-float-aligned, reserve
   46:     \G enough space to align it.
   47:     here dup sfaligned swap ?DO  bl c,  LOOP ;
   48: : dfalign ( -- ) \ float-ext d-f-align
   49:     \G If the data-space pointer is not double-float-aligned, reserve
   50:     \G enough space to align it.
   51:     here dup dfaligned swap ?DO  bl c,  LOOP ;
   52: 
   53: (Field) sfloat+ ( sf-addr1 -- sf-addr2 ) \ float-ext s-float-plus
   54: \G @code{1 sfloats +}.
   55:     1 sfloats ,
   56: 
   57: (Field) dfloat+ ( df-addr1 -- df-addr2 ) \ float-ext d-float-plus
   58: \G @code{1 dfloats +}.
   59:     1 dfloats ,
   60:     
   61: : f, ( f -- ) \ gforth
   62:     \G Reserve data space for one floating-point number and store
   63:     \G @i{f} in the space.
   64:     here 1 floats allot f! ;
   65: 
   66: : fconstant  ( r "name" -- ) \ float f-constant
   67:     Create f,
   68: DOES> ( -- r )
   69:     f@ ;
   70: 
   71: : fdepth ( -- +n ) \ float f-depth
   72:     \G @i{+n} is the current number of (floating-point) values on the
   73:     \G floating-point stack.
   74:     fp0 @ fp@ - [ 1 floats ] Literal / ;
   75: 
   76: : FLiteral ( compilation r -- ; run-time -- r ) \ float f-literal
   77:     \G Compile appropriate code such that, at run-time, @i{r} is placed
   78:     \G on the (floating-point) stack. Interpretation semantics are undefined.
   79:     BEGIN  here cell+ cell+ dup faligned <>  WHILE  postpone noop  REPEAT
   80:     postpone ahead here >r f, postpone then
   81:     r> postpone literal postpone f@ ;  immediate
   82: 
   83: &15 Value precision ( -- u ) \ float-ext
   84: \G @i{u} is the number of significant digits currently used by
   85: \G @code{F.} @code{FE.} and @code{FS.} 
   86: : set-precision ( u -- ) \ float-ext
   87:     \G Set the number of significant digits currently used by
   88:     \G @code{F.} @code{FE.} and @code{FS.} to @i{u}.
   89:     to precision ;
   90: 
   91: : scratch ( r -- addr len )
   92:   pad precision - precision ;
   93: 
   94: : zeros ( n -- )   0 max 0 ?DO  '0 emit  LOOP ;
   95: 
   96: : -zeros ( addr u -- addr' u' )
   97:   BEGIN  dup  WHILE  1- 2dup + c@ '0 <>  UNTIL  1+  THEN ;
   98: 
   99: : f$ ( f -- n )  scratch represent 0=
  100:   IF  2drop  scratch 3 min type  rdrop  EXIT  THEN
  101:   IF  '- emit  THEN ;
  102: 
  103: : f.  ( r -- ) \ float-ext f-dot
  104: \G Display (the floating-point number) @i{r} without exponent,
  105: \G followed by a space.
  106:   f$ dup >r 0<=
  107:   IF    '0 emit
  108:   ELSE  scratch r@ min type  r@ precision - zeros  THEN
  109:   '. emit r@ negate zeros
  110:   scratch r> 0 max /string 0 max -zeros type space ;
  111: \ I'm afraid this does not really implement ansi semantics wrt precision.
  112: \ Shouldn't precision indicate the number of places shown after the point?
  113: 
  114: \ Why do you think so? ANS Forth appears ambiguous on this point. -anton.
  115: 
  116: : fe. ( r -- ) \ float-ext f-e-dot
  117: \G Display @i{r} using engineering notation (with exponent dividable
  118: \G by 3), followed by a space.
  119:   f$ 1- s>d 3 fm/mod 3 * >r 1+ >r
  120:   scratch r@ tuck min tuck - >r type r> zeros
  121:   '. emit scratch r> /string type
  122:   'E emit r> . ;
  123: 
  124: : fs. ( r -- ) \ float-ext f-s-dot
  125: \G Display @i{r} using scientific notation (with exponent), followed
  126: \G by a space.
  127:   f$ 1-
  128:   scratch over c@ emit '. emit 1 /string type
  129:   'E emit . ;
  130: 
  131: : sfnumber ( c-addr u -- r true | false )
  132:     2dup [CHAR] e scan ( c-addr u c-addr2 u2 )
  133:     dup 0=
  134:     IF
  135: 	2drop 2dup [CHAR] E scan ( c-addr u c-addr3 u3 )
  136:     THEN
  137:     nip
  138:     IF
  139: 	>float
  140:     ELSE
  141: 	2drop false
  142:     THEN ;
  143: 
  144: [ifundef] compiler-notfound1
  145: defer compiler-notfound1
  146: ' no.extensions IS compiler-notfound1
  147: 
  148: :noname compiler-notfound1 execute ; is compiler-notfound
  149: 
  150: defer interpreter-notfound1
  151: ' no.extensions IS interpreter-notfound1
  152: 
  153: :noname interpreter-notfound1 execute ; is interpreter-notfound
  154: [then]
  155: 
  156: :noname ( c-addr u -- ... xt )
  157:     2dup sfnumber
  158:     IF
  159: 	2drop [comp'] FLiteral
  160:     ELSE
  161: 	defers compiler-notfound1
  162:     ENDIF ;
  163: IS compiler-notfound1
  164: 
  165: :noname ( c-addr u -- ... xt )
  166:     2dup sfnumber
  167:     IF
  168: 	2drop ['] noop
  169:     ELSE
  170: 	defers interpreter-notfound1
  171:     ENDIF ;
  172: IS interpreter-notfound1
  173: 
  174: : fvariable ( "name" -- ) \ float f-variable
  175:     Create 0.0E0 f, ;
  176:     \ does> ( -- f-addr )
  177: 
  178: 1.0e0 fasin 2.0e0 f* fconstant pi ( -- r ) \ gforth
  179: \G @code{Fconstant} -- @i{r} is the value pi; the ratio of a circle's area
  180: \G to its diameter.
  181: 
  182: : f2* ( r1 -- r2 ) \ gforth
  183:     \G Multiply @i{r1} by 2.0e0
  184:     2.0e0 f* ;
  185: 
  186: : f2/ ( r1 -- r2 ) \ gforth
  187:     \G Multiply @i{r1} by 0.5e0
  188:     0.5e0 f* ;
  189: 
  190: : 1/f ( r1 -- r2 ) \ gforth
  191:     \G Divide 1.0e0 by @i{r1}.
  192:     1.0e0 fswap f/ ;
  193: 
  194: get-current environment-wordlist set-current
  195: 1.7976931348623157e308 FConstant max-float
  196: set-current
  197: 
  198: \ We now have primitives for these, so we need not define them
  199: 
  200: \ : falog ( f -- 10^f )  [ 10.0e0 fln ] FLiteral f* fexp ;
  201: 
  202: \ : fsinh    fexpm1 fdup fdup 1.0e0 f+ f/ f+ f2/ ;
  203: \ : fcosh    fexp fdup 1/f f+ f2/ ;
  204: \ : ftanh    f2* fexpm1 fdup 2.0e0 f+ f/ ;
  205: 
  206: \ : fatanh   fdup f0< >r fabs 1.0e0 fover f- f/  f2* flnp1 f2/
  207: \            r> IF  fnegate  THEN ;
  208: \ : facosh   fdup fdup f* 1.0e0 f- fsqrt f+ fln ;
  209: \ : fasinh   fdup fdup f* 1.0e0 f+ fsqrt f/ fatanh ;
  210: 
  211: : f~abs ( r1 r2 r3 -- flag ) \ gforth
  212:     \G Approximate equality with absolute error: |r1-r2|<r3.
  213:     frot frot f- fabs fswap f< ;
  214: 
  215: : f~rel ( r1 r2 r3 -- flag ) \ gforth
  216:     \G Approximate equality with relative error: |r1-r2|<r3*|r1+r2|.
  217: 	frot frot fover fabs fover fabs f+ frot frot
  218: 	f- fabs frot frot f* f< ;
  219: 
  220: : f~ ( r1 r2 r3 -- flag ) \ float-ext f-proximate
  221:     \G ANS Forth medley for comparing r1 and r2 for equality: r3>0:
  222:     \G @code{f~abs}; r3=0: bitwise comparison; r3<0: @code{fnegate f~rel}.
  223:     fdup f0=
  224:     IF \ bitwise comparison
  225: 	fp@ float+ 1 floats over float+ over str=
  226: 	fdrop fdrop fdrop
  227: 	EXIT
  228:     THEN
  229:     fdup f0>
  230:     IF
  231: 	f~abs
  232:     ELSE
  233: 	fnegate f~rel
  234:     THEN ;
  235: 
  236: -0e 8 0 [do] fp@ [i] + c@ $80 = [if] [i] constant fsign-offset [then] [loop]
  237: 
  238: : fcopysign ( r1 r2 -- r3 ) \ gforth
  239: \G r3 takes its absolute value from r1 and its sign from r2
  240:     \ !! implementation relies on IEEE DP format
  241:     fp@ fsign-offset + dup c@ $80 and >r ( r1 r2 addr-r1sign )
  242:     float+ dup c@ $7f and r> or swap c!
  243:     fdrop ;
  244: 
  245: \ proposals from Krishna Myeni in <cjsp2d$47l$1@ngspool-d02.news.aol.com>
  246: \ not sure if they are a good idea
  247: 
  248: : ftrunc ( r1 -- r2 ) \ X:ftrunc
  249:     \ round towards 0
  250:     fdup fabs floor fswap fcopysign ;
  251: 
  252: : FMOD ( r1 r2 -- r )
  253:     \ remainder of r1/r2
  254:     FOVER FOVER F/ ftrunc F* F- ;
  255: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>