Win32Forth implements the full ANSI floating-point and floating-point extension wordsets as well as a number of useful extra words. It uses a separate floating-point stack (implemented in the USER area for task safety).
The floating-point words can be compiled as 8 byte (for speed) or 10 byte (for accuracy). The default when the system is built is 8 byte, but can be set to 10 byte (in src\extend.f) by altering the CONSTANT B/FLOAT and re-extending the system (using setup.exe). If the CONSTANT is not defined then the file automatically creates it and compiles the code for 10 byte floats.
The only error that is thrown is for FP stack Underflow (error code -45); arithmetic operations which produce values too large to be represented use infinity, while indeterminate results produce NANs.
The following words are for examining, saving, restoring and changing the state of the
x87 FPU. They are not normally needed by applications although they can be useful for
dealing with legacy code, which requires different rounding modes, precision, or
exception handling.
Since the default error handler resets the control word then applications that use
other settings will need to CATCH all exceptions or modify the error handler.
NOTE if programs unmask exceptions then they need to handle their own errors.
For information on the settings and writng exception handlers refer to the INTEL
processor documentation.
WARNING! do not alter the settings unless you know what you're doing.
code >fregs ( addr -- ) \ W32F Floating extra
Restore x87 FPU State.
code >fregs> ( addr -- ) \ W32F Floating extra
Save and Restore x87 FPU State.
code fpcw> ( -- n ) \ W32F Floating extra
Get x87 FPU Control Word.
code >fpcw ( n -- ) \ W32F Floating extra
Set x87 FPU Control Word.
code fpsw> ( -- n ) \ W32F Floating extra
Get x87 FPU Status Word.
10 constant B/FLOAT ( -- n ) \ W32F Floating extra
Number of bytes in a floating-point number. Note the default is 8 bytes.
value cells/float
Number of cells in a floating-point number. If the number of bytes is not a multiple of 4 this is rounded up.
cell NEWUSER FLOATSP ( -- addr ) \ W32F Floating extra
Address of floating point stack pointer in the user area.
code finit ( -- ) \ W32F Floating extra
Clears the floating-point stack & sets the appropriate byte mode. It is executed by the system on start-up and by the default exception handler. Users generally don't need to call this word in a single-task program. Tasks in a multi-task program should execute this word before executing any other floating-point words.
code F@ ( addr -- ; fs: -- r ) \ ANSI Floating
Fetch a float.
code SF@ ( addr -- ; fs: -- r ) \ ANSI Floating ext
Fetch a 32 bit (short) float.
code DF@ ( addr -- ; fs: -- r ) \ ANSI Floating ext
Fetch a 64 bit (double) float.
code F! ( addr -- ; fs: r -- ) \ ANSI Floating
Store a float.
code SF! ( addr -- ; fs: r -- ) \ ANSI Floating ext
Store a 32 bit (short) float.
code DF! ( addr -- ; fs: r -- ) \ ANSI Floating ext
Store a 64 bit (double) float.
code F+! ( addr -- ; fs: r -- ) \ W32F Floating extra
Add the value to a float.
: F, ( fs: r -- ) \ W32F Floating extra
Compile a float into the dictionary.
: FVARIABLE ( compiling -<name>- -- ; run-time -- addr) \ ANSI Floating
Define a floating-point variable in the dictionary. The contents are undefined.
: FVALUE ( compiling -<name>- -- ; fs: r -- ; run-time FS: -- r ) \ W32F Floating extra
Define a floating point value initialised from the FP stack.
: FTO \ W32F Floating extra
Interpretation: ( -<fvalue>- -- fs: r -- )
Compilation: ( -<fvalue>- -- Run-time: FS: r -- )
Store r into -<fvalue>-. If -<fvalue>- is not defined with fvalue then memory may be corrupted; no checks are made so the user should take care. FTO should not be POSTPONEd.
: FCONSTANT ( -<name>- ; fs: r -- ) \ ANSI Floating
Interpretation: ( -<name>- ; fs: r -- )
Define an FP constant.
Compilation:
Append the run-time semantics given below to the current definition.
Run-time: ( fs: -- r )
Place r on the floating-point stack.
: FLITERAL ( Compilation fs: r -- ; Runtime fs: -- r ) \ ANSI Floating
Interpretation:
Interpretation semantics for this word are undefined.
Compilation: ( fs: r -- )
Append the run-time semantics given below to the current definition.
Run-time: ( fs: -- r )
Place r on the floating-point stack.
code FDROP ( fs: r -- ) \ ANSI Floating
Remove r from the floating-point stack.
code FDUP ( fs: r -- r r ) \ ANSI Floating
Duplicate the top entry on the floating-point stack.
code FSWAP ( fs: r1 r2 -- r2 r1 ) \ ANSI Floating
Exchange the top 2 FP numbers.
code FOVER ( fs: r1 r2 -- r1 r2 r1 ) \ ANSI Floating
Copy the 2nd FP stack number to the top of the FP stack.
code FROT ( fs: r1 r2 r3 -- r2 r3 r1 ) \ ANSI Floating
Rotate the top 3 FP stack numbers.
code FPICK ( n -- ; fs: -- r ) \ W32F Floating extra
Copy the n'th number from the FP stack.
: FNIP ( fs: r1 r2 -- r2 ) \ W32F Floating extra
Remove the 2nd FP stack entry.
The following words can be used for pairs of FP numbers and are useful for dealing with complex numbers or 2-dimensional vectors on the FP stack.
code F2DROP ( fs: r1 r2 -- ) \ W32F Floating extra
Remove the top 2 FP stack entries.
: F2DUP ( fs: r1 r2 -- r1 r2 r1 r2 ) \ W32F Floating extra
Duplicate the top 2 FP stack entries.
: F2SWAP ( fs: r1 r2 r3 r4 -- r3 r4 r1 r2 ) \ W32F Floating extra
Swap the top pair of floating-point numbers with the second pair.
: F2NIP ( fs: r1 r2 r3 r4 -- r3 r4 ) \ W32F Floating extra
Remove the 2nd pair of FP stack entries.
code fpi ( fs: -- r ) \ W32F Floating extra
Push the value 3.141596... on to the FP stack.
code f0.0 ( fs: -- r ) \ W32F Floating extra
Push plus zero on to the FP stack.
code f1.0 ( fs: -- r ) \ W32F Floating extra
Push the value 1.0 on to the FP stack.
code fL2t ( fs: -- r ) \ W32F Floating extra
Push the value of log base 2 of 10.
code fL2e ( fs: -- r ) \ W32F Floating extra
Push the value of log base 2 of e.
code fLog2 ( fs: -- r ) \ W32F Floating extra
Push the value of log base 10 of 2.
code fLn2 ( fs: -- r ) \ W32F Floating extra
Push the value of ln 2 (the natural logarithm).
fconstant finf ( fs: -- r ) \ W32F Floating extra
Push plus infinity.
2e0 fconstant f2.0 ( fs: -- r ) \ W32F Floating extra
Push floating-point 2.0.
10e0 fconstant f10.0 ( fs: -- r ) \ W32F Floating extra
Push floating-point 10.0.
5e-1 fconstant f0.5 ( fs: -- r ) \ W32F Floating extra
Push floating-point 0.5.
f0.0 fconstant fbig ( fs: -- r ) \ W32F Floating extra
Push the largest non-infinite floating-point number.
f0.0 fconstant feps ( fs: -- r ) \ W32F Floating extra
Push the smallest non-zero floating-point number.
f1.0 fconstant fsmall ( fs: -- r ) \ W32F Floating extra
Push the smallest non-denormalised floating-point number.
fvariable a2**63 ( -- addr ) \ W32F Floating extra
Return the address of a float containing 2**63.
fvariable sq2m1 ( -- addr ) \ W32F Floating extra
Return the address of a float containing sqrt(2) - 1.
fvariable sq2/2m1 ( -- addr ) \ W32F Floating extra
Return the address of a float containing sqrt(2)/2 - 1.
code FLOOR ( fs: r1 -- r2 ) \ ANSI Floating
Round r1 to an integral value using the round toward negative infinity rule, giving r2.
code FCEIL ( fs: r1 -- r2 ) \ W32F Floating extra
Round r1 to an integral value using the round toward positive infinity rule, giving r2.
code FTRUNC ( fs: r1 -- r2 ) \ W32F Floating extra
Round r1 to an integral value using the round toward zero rule, giving r2.
code FROUND ( fs: r1 -- r2 ) \ ANSI Floating
Round r1 to an integral value using the round to nearest rule, giving r2.
code D>F ( d -- ; Fs: -- r ) \ ANSI Floating
Convert double number to floating-point number.
code F>D ( -- d ; fs: r -- ) \ ANSI Floating
Convert floating-point number to double number, by rounding towards zero. If the
result would be too large to fit in a double number then
-9223372036854775808
is returned.
code ZF>D ( -- d ; fs: r -- ) \ W32F Floating extra
Convert floating-point number to double number, using the current rounding mode
(rounding towards nearest unless changed by the user). If the result would be too
large to fit in a double number then
-9223372036854775808 is returned.
: s>f ( n -- ; fs: -- r ) \ W32F Floating extra
Convert the single number n to floating point number r.
: f>s ( -- n ; fs: r -- ) \ W32F Floating extra
Convert the floating point number r to single number n.
code FS>DS ( -- dfloat fs: r -- ) \ W32F Floating extra
Move floating point number bits to the data stack as a 64-bit float. This function is for passing floats to DLLs.
code SFS>DS ( -- float ; fs: r -- ) \ W32F Floating extra
Push the top of the float stack onto the data stack as a 32-bit float. This function is for passing floats to DLLs.
: F0= ( -- f ; fs: r -- ) \ ANSI Floating
Return true if r equals ±0e0. Returns false for NAN.
: F0< ( -- f ; fs: r -- ) \ ANSI Floating
Return true if r is less than ±0e0. Returns false for NAN.
: f0> ( -- f ; fs: r -- ) \ W32F Floating extra
Return true if r is greater than ±0e0. Returns false for NAN.
: f= ( -- f ; fs: r1 r2 -- ) \ W32F Floating extra
Return true if r1 equals r2. Returns false if either number is a NAN.
: F< ( -- f ; fs: r1 r2 -- ) \ ANSI Floating
Return true if r1 is less than r2. Returns false if either number is a NAN.
: f> ( -- f ; fs: r1 r2 -- ) \ W32F Floating extra
Return true if r1 is greater than r2. Returns false if either number is a NAN.
: f<= ( -- f ; fs: r1 r2 -- ) \ W32F Floating extra
Return true if r1 is less than or equal to r2. Returns true if either number is a NAN.
: f>= ( -- f ; fs: r1 r2 -- ) \ W32F Floating extra
Return true if r1 is greater than or equal to r2. Returns true if either number is a NAN.
: FMAX ( fs: r1 r2 -- r3 ) \ ANSI Floating
Return r3 the maximum of r1 and r2. If r1 is a NAN then so is r3. If r2 is a NAN then r3=r1.
: FMIN ( fs: r1 r2 -- r3 ) \ ANSI Floating
Return r3 the minimum of r1 and r2. If r1 is a NAN then so is r3. If r2 is a NAN then r3=r1.
code F+ ( fs: r1 r2 -- r3 ) \ ANSI Floating
Add r1 to r2.
code F- ( fs: r1 r2 -- r3 ) \ ANSI Floating
Subtract r2 from r1.
code F* ( fs: r1 r2 -- r3 ) \ ANSI Floating
Multiply r1 by r2.
code F/ ( fs: r1 r2 -- r3 ) \ ANSI Floating
Divide r1 by r2.
code FNEGATE ( fs: r1 -- r2 ) \ ANSI Floating
Reverse the sign of r1.
: 1/f ( fs: r1 -- r2 ) \ W32F Floating extra
r2 is the reciprocal of r1.
code f2* ( fs: r1 -- r2 ) \ W32F Floating extra
Multiply by 2.
code f2/ ( fs: r1 -- r2 ) \ W32F Floating extra
Divide by 2.
code FABS ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the absolute value of r1.
code FSQRT ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the positive square root of r1. r2 is NAN for negative r1.
: F~ ( -- flag ; fs: r1 r2 r3 -- ) \ ANSI Floating ext
If r3 is positive, flag is true if the absolute value of (r1 minus r2) is less than r3. If r3 is zero, flag is true if the implementation-dependent encoding of r1 and r2 are exactly identical (positive and negative zero are unequal). If r3 is negative, flag is true if the absolute value of (r1 minus r2) is less than the absolute value of r3 times the sum of the absolute values of r1 and r2.
This provides the three types of floating point equality in common use -- close in absolute terms, exact equality as represented, and relatively close.
: FSIN ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the sine of r1 in radians.
: FCOS ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the cosine of r1 in radians.
: FSINCOS ( fs: r1 -- r2 r3 ) \ ANSI Floating ext
r2 is the sine and r3 the cosine of r1 in radians. This function is more efficient than calling FSIN and FCOS separately.
: FTAN ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the tangent of r1 in radians.
code FASIN ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the radian angle whose sine is r1. The result for |x| =< 1 is between ±pi/2. The result for |x| > 1 is NAN.
code FACOS ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the radian angle whose cosine is r1. The result for |x| =< 1 is between 0 and pi. The result for |x| > 1 is NAN
code FATAN ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the radian angle whose tangent is r1. The result is between ±pi/2.
code FATAN2 ( fs: r1 r2 -- r3 ) \ ANSI Floating ext
r3 is the radian angle whose tangent is r1/r2. The result is between ±pi with the same sign as r2. If r1 and r2 are both zero then r3 is ±zero. This function can be used to convert cartesian coordinates into the angle of the polar coordinates.
code FLN ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the natural logarithm of r1. If r1 is ±0 then r2 is -infinity. If r1 is infinity then r2 is infinity. If r1 is less than zero then r2 is a NAN.
code FLNP1 ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the natural logarithm of the quantity r1 plus one. If r1 is -1.0 then r2 is -infinity. If r1 is infinity then r2 is infinity. If r1 is less than -1.0 then r2 is a NAN.
code FLOG ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the logarithm to base 10 of r1. If r1 is ±0 then r2 is -infinity. If r1 is infinity then r2 is infinity. If r1 is less than zero then r2 is a NAN.
code FEXP ( fs: r1 -- r2 ) \ ANSI Floating ext
Raise e to the power r1, giving r2.
code FEXPM1 ( fs: r1 -- r2 ) \ ANSI Floating ext
Raise e to the power r1 and subtract one, giving r2.
This function allows accurate computation when its arguments are close to zero, and provides a useful base for the standard exponential functions. Hyperbolic functions such as cosh(x) can be efficiently and accurately implemented by using FEXPM1; accuracy is lost in this function for small values of x if the word FEXP is used.
: f** ( fs: r1 r2 -- r3 ) \ ANSI Floating ext
Raise r1 to the power r2, giving the product r3.
: FALOG ( fs: r1 -- r2 ) \ ANSI Floating ext
Raise ten to the power r1, giving r2.
: FSINH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the hyperbolic sine of r1.
: FCOSH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the hyperbolic cosine of r1.
: FTANH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the hyperbolic tangent of r1, |r2| <= 1.
code FASINH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the number whose hyperbolic sine is r1.
code FACOSH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the number whose hyperbolic cosine is r1. If r1 < 1.0 then r2 is a NAN.
: FATANH ( fs: r1 -- r2 ) \ ANSI Floating ext
r2 is the number whose hyperbolic tangent is r1. IF |r1| > 1.0 then r2 is a NAN.
: >FLOAT ( addr len -- f ; fs: -- r | <nothing> ) \ ANSI Floating
An attempt is made to convert the string specified by c-addr and u to internal
floating-point representation. If the string represents a valid floating-point
number in the syntax below, its value r and true are returned. If the string does not
represent a valid floating-point number only false is returned.
A string of blanks is treated as a special case representing zero.
The syntax of a convertible string := <significand>[<exponent>] <significand> := [<sign>]{<digits>[.<digits0>] | .<digits> } <exponent> := <marker><digits0> <marker> := {<e-form> | <sign-form>} <e-form> := <e-char>[<sign-form>] <sign-form> := { + | - } <e-char> := { D | d | E | e }
: f# ( Interpretation: "fp no." -- ; fs: -- r ) \ W32F Floating extra
( Compilation: "fp no." -- ; run-time: fs: -- r )
An attempt is made to convert the space delimited string following F# to internal
floating-point representation. If the string represents a valid floating-point
number in the syntax below, its value r is returned. If the string does not
represent a valid floating-point number an error is thrown.
F# used at the end of a line is treated as a special case representing zero.
If interpreting the FP number is placed on the FP stack, while it is compiled as
an Fliteral if compiling.
The syntax of a convertible string is the same as >FLOAT .
: REPRESENT ( addr u -- n flag1 flag2 ; fs: r -- ) \ ANSI Floating
At c-addr, place the character-string external representation of the significand of
the floating-point number r. Return the decimal-base exponent as n, the sign as flag1
and valid result as flag2. The character string shall consist of the u most significant
digits of the significand represented as a decimal fraction with the implied decimal
point to the left of the first digit, and the first digit zero only if all digits
are zero. The significand is rounded to u digits following the round to nearest
rule; n is adjusted, if necessary, to correspond to the rounded magnitude of the
significand. If flag2 is true then r was in the implementation-defined range of
floating-point numbers. If flag1 is true then r is negative.
An ambiguous condition exists if the value of BASE is not decimal ten.
When flag2 is false, n is 7FFFFFFF and flag1 is the sign. The contents of c-addr are
the first u characters of either NAN or Infinity, padded with spaces if necessary.
: PRECISION ( -- u ) \ ANSI Floating ext
Return the number of significant digits currently used by (F.), (FE.), (FS.), F., FE., or FS. as u.
: SET-PRECISION ( u -- ) \ ANSI Floating ext
Set the number of significant digits currently used by (F.), (FE.), (FS.), F., FE., or FS. to u.
: min-precision ( u -- ) \ W32F Floating extra
Set the number of significant digits currently used by (F.), (FE.), (FS.), F., FE., or FS. to u if it is greater than the present setting.
The following words are for formatting floating point numbers as counted strings in the buffer whose address is supplied so they can be used for purposes other than printing the numbers to the console. The string is not null terminated.
: (F.) ( addr -- ; fs: r -- ) \ W32F Floating extra
Format the top number on the floating-point stack using fixed-point notation:
[-] <digits>.<digits0>
: (FE.) ( addr -- ; fs: r -- ) \ W32F Floating extra
Format r as a string in engineering notation.
: (FS.) ( addr -- ; fs: r -- ) \ W32F Floating extra
Format r as a string in scientific notation:
<significand><exponent>
where:
<significand> := [-]<digit>.<digits0> <exponent> := E[-]<digits>
SYNONYM (E.) (FS.) ( addr -- ; fs: r -- ) \ W32F Floating extra
See above.
: (G.) ( addr -- ; fs: r -- ) \ W32F Floating extra
Format r as a string using scientific notation or ordinary representation according to the size of r.
: F. ( fs: r -- ) \ ANSI Floating ext
Display, with a trailing space, the top number on the floating-point stack using fixed-point notation:
[-] <digits>.<digits0>
: FE. ( fs: r -- ) \ ANSI Floating ext
Display, with a trailing space, the top number on the floating-point stack using engineering notation, where the significand is greater than or equal to 1.0 and less than 1000.0 and the decimal exponent is a multiple of three.
: FS. ( fs: r -- ) \ ANSI Floating ext
Display, with a trailing space, the top number on the floating-point stack in scientific notation:
<significand><exponent>
where:
<significand> := [-]<digit>.<digits0> <exponent> := E[-]<digits>
SYNONYM E. FS. ( fs: r -- ) \ W32F Floating extra
See above.
: G. ( fs: r -- ) \ W32F Floating extra
Display the top number on the floating-point stack using scientific notation or ordinary representation according to the size of r.
: f.s ( -- ) \ W32F Floating debug
Display floating point stack.
: .fdepth ( -- ) \ W32F Floating debug
Display depth of floating point stack.
: fdump ( -- ) \ W32F Floating debug
Dump of the real Floating Point Unit.
If you reset the FPU control word to use other than the default rounding or precision values then you may need to modify the default error handling. In version V6.10 or higher this can be done by defining your own handler, MY-RESET-STACKS then adding it in thus;
reset-stacks-chain chain-add my-reset-stacks Ealier versions need to add : new-reset-stacks [ defer@ reset-stacks compile, ] my-reset-stacks ; new-reset-stacks is reset-stacks
You can test for the presence of NANs with; .... fdup f= 0= .... which returns true only for NANs. You can test for both NANs and infinities with; .... fdup f- f0= 0= and for infinities with; .... fabs finf f=
Document $Id: p-float.htm,v 1.23 2007/05/26 10:24:11 dbu_de Exp $