$ gforth
Gforth 0.7.9_20260324
...
Type `help' for basic help
1.9e floor ok f:1
f. 1. ok
1.9e fceil
*the terminal*:6:6: error: Undefined word
1.9e >>>fceil<<<
Backtrace:
/usr/share/gforth/0.7.9_20260324/kernel/recognizer.fs:124:35:Â 0 $7DFF9A013568 throw
: fceil ( r1 -- r2 ) fnegate floor fnegate ; ok
1.9e fceil f. 2. ok
-1.9e fceil f. -1. ok
On 24/04/2026 9:11 am, Buzz McCool wrote:
$ gforth
Gforth 0.7.9_20260324
...
Type `help' for basic help
1.9e floor ok f:1
f. 1. ok
1.9e fceil
*the terminal*:6:6: error: Undefined word
1.9e >>>fceil<<<
Backtrace:
/usr/share/gforth/0.7.9_20260324/kernel/recognizer.fs:124:35:Â 0 $7DFF9A013568 throw
: fceil ( r1 -- r2 ) fnegate floor fnegate ; ok
1.9e fceil f. 2. ok
-1.9e fceil f. -1. ok
On 4/23/26 8:14 PM, dxf wrote:
On 24/04/2026 9:11 am, Buzz McCool wrote:
$ gforth
Gforth 0.7.9_20260324
...
Type `help' for basic help
1.9e floor ok f:1
f. 1. ok
1.9e fceil
*the terminal*:6:6: error: Undefined word
1.9e >>>fceil<<<
Backtrace:
/usr/share/gforth/0.7.9_20260324/kernel/recognizer.fs:124:35: 0 $7DFF9A013568 throw
: fceil ( r1 -- r2 ) fnegate floor fnegate ; ok
1.9e fceil f. 2. ok
-1.9e fceil f. -1. ok
You may want to check the behavior of FLOOR and FCEIL with IEEE special values, if your Forth system supports them. The following code should
run on both 32-bit and 64-bit Forth systems, with or without a separate
fp stack. Some of the tests may be redundant.
--
KM
\ ============
\ Requires ttester.4th
DECIMAL
0e fconstant F=ZERO
HEX
\ Make an IEEE 754 double precision floating point value from
\ the specified bits for the sign, binary fraction, and exponent.
\ Return the fp value and error code with the following meaning:
\ 0 no error
\ 1 exponent out of range
\ 2 fraction out of range
fvariable temp
: MAKE-IEEE-DFLOAT ( signbit udfraction uexp -- r nerror )
dup 800 u< invert IF 2drop 2drop F=ZERO 1 EXIT THEN
14 lshift 3 pick 1F lshift or >r
dup 100000 u< invert IF
r> 2drop 2drop F=ZERO 2 EXIT
THEN
r> or [ temp 4 + ] literal L! temp L!
drop temp df@ 0 ;
\ Constants representing -0e -INF +INF -NAN +NANHow is your F= defined?
true 0 0 0 make-ieee-dfloat [IF] fdrop [ELSE] fconstant F=-ZERO [THEN]
true 0 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -INF [THEN]
[DEFINED] -INF [IF] -INF fnegate fconstant +INF [THEN]
true 1 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -NAN [THEN] [DEFINED] -NAN [IF] -NAN fnegate fconstant +NAN [THEN]
DECIMAL
: FCEIL ( F: r1 -- r2 ) FNEGATE FLOOR FNEGATE ;
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
1 cells 4 < Abort" Tests not available for cell size < 32 bits"
1 cells 8 = constant 64-bit?
\ fetch double float onto the data stack for comparison
64-bit? [IF]
: fetch-df ( addr -- u ) @ ;
: equal-df = ; \ bitwise equivalence
[ELSE]
: fetch-df ( addr -- ud ) 2@ ;
: equal-df d= ; \ bitwise equivalence
[THEN]
\ Testing bitwise inequality of positive and negative special values
create r1 8 allot \ allot dfloat
create r2 8 allot \ allot dfloat
t{ F=ZERO r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
t{ +INF r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
t{ +NAN r1 DF! -> }t
t{ -NAN r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
TESTING FLOOR with IEEE 754 Special values
t{ F=ZERO FLOOR r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ F=-ZERO FLOOR r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -INF FLOOR r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ +INF FLOOR r1 DF! -> }t
t{ +INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -NAN FLOOR -NAN F= -> true }t
t{ -NAN FLOOR +NAN F= -> true }t
t{ +NAN FLOOR -NAN F= -> true }t
t{ +NAN FLOOR +NAN F= -> true }t
t{ 0.1e FLOOR r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -0.1e FLOOR r1 DF! -> }t
t{ -1.0e r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
TESTING FCEIL with IEEE 745 values
t{ F=ZERO FCEIL r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ F=-ZERO FCEIL r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -INF FCEIL r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ +INF FCEIL r1 DF! -> }t
t{ +INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -NAN FCEIL -NAN F= -> true }t
t{ -NAN FCEIL +NAN F= -> true }t
t{ +NAN FCEIL -NAN F= -> true }t
t{ +NAN FCEIL +NAN F= -> true }t
t{ 0.1e FCEIL r1 DF! -> }t
t{ 1.0e r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -0.1e FCEIL r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
\ end of tests
\ ============
On Mon, 27 Apr 2026 17:39:11 -0500F= is undefined in standard Forth. However common sense should prevail
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 4/23/26 8:14 PM, dxf wrote:
On 24/04/2026 9:11 am, Buzz McCool wrote:
$ gforth
Gforth 0.7.9_20260324
...
Type `help' for basic help
1.9e floor ok f:1
f. 1. ok
1.9e fceil
*the terminal*:6:6: error: Undefined word
1.9e >>>fceil<<<
Backtrace:
/usr/share/gforth/0.7.9_20260324/kernel/recognizer.fs:124:35:Â 0 $7DFF9A013568 throw
: fceil ( r1 -- r2 ) fnegate floor fnegate ; ok
1.9e fceil f. 2. ok
-1.9e fceil f. -1. ok
You may want to check the behavior of FLOOR and FCEIL with IEEE special
values, if your Forth system supports them. The following code should
run on both 32-bit and 64-bit Forth systems, with or without a separate
fp stack. Some of the tests may be redundant.
--
KM
\ ============
\ Requires ttester.4th
DECIMAL
0e fconstant F=ZERO
HEX
\ Make an IEEE 754 double precision floating point value from
\ the specified bits for the sign, binary fraction, and exponent.
\ Return the fp value and error code with the following meaning:
\ 0 no error
\ 1 exponent out of range
\ 2 fraction out of range
fvariable temp
: MAKE-IEEE-DFLOAT ( signbit udfraction uexp -- r nerror )
dup 800 u< invert IF 2drop 2drop F=ZERO 1 EXIT THEN
14 lshift 3 pick 1F lshift or >r
dup 100000 u< invert IF
r> 2drop 2drop F=ZERO 2 EXIT
THEN
r> or [ temp 4 + ] literal L! temp L!
drop temp df@ 0 ;
\ Constants representing -0e -INF +INF -NAN +NAN
true 0 0 0 make-ieee-dfloat [IF] fdrop [ELSE] fconstant F=-ZERO [THEN]
true 0 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -INF [THEN]
[DEFINED] -INF [IF] -INF fnegate fconstant +INF [THEN]
true 1 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -NAN [THEN]
[DEFINED] -NAN [IF] -NAN fnegate fconstant +NAN [THEN]
DECIMAL
: FCEIL ( F: r1 -- r2 ) FNEGATE FLOOR FNEGATE ;
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
On Mon, 27 Apr 2026 17:39:11 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
I was just looking for my IEEE 754 documentation, but I think you are
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
BR
Peter
On 4/28/26 6:40 AM, peter wrote:
On Mon, 27 Apr 2026 17:39:11 -0500...
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
I was just looking for my IEEE 754 documentation, but I think you are correct that +NAN should not equal itself or -NAN, since the equality comparison is not valid for NANs.
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
BR
Peter
I am using the x87 FCOMP instruction, which I expected to have IEEE-compatible behavior. Will need to look closer at this.
On 4/28/26 6:40 AM, peter wrote:
On Mon, 27 Apr 2026 17:39:11 -0500...
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
I was just looking for my IEEE 754 documentation, but I think you are correct that +NAN should not equal itself or -NAN, since the equality comparison is not valid for NANs.
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
BR
Peter
I am using the x87 FCOMP instruction, which I expected to have IEEE-compatible behavior. Will need to look closer at this.
On 29/04/2026 10:25 am, Krishna Myneni wrote:
On 4/28/26 6:40 AM, peter wrote:
On Mon, 27 Apr 2026 17:39:11 -0500...
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
I was just looking for my IEEE 754 documentation, but I think you are correct that +NAN should not equal itself or -NAN, since the equality comparison is not valid for NANs.
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
BR
Peter
I am using the x87 FCOMP instruction, which I expected to have IEEE-compatible behavior. Will need to look closer at this.
I used FCOMP and got the expected results.
\ fsp points to separate f/p stack in memory
label tst
addr fsp ) di mov
qword 1 floats [di] fld qword 0 [di] fld fcompp
ax fstsw st(0) fstp 2 floats # addr fsp ) add
41 # ah and bx bx sub cl ah cmp 1 $ jnz bx dec
1 $: bx push next
end-code
code F< ( r1 r2 -- flag ) 00 # cl mov tst ju end-code
code F> ( r1 r2 -- flag ) 01 # cl mov tst ju end-code
code F= ( r1 r2 -- flag ) 40 # cl mov tst ju end-code
+NAN +NAN F= . 0 ok
+NAN -NAN F= . 0 ok
On 4/28/26 8:20 PM, dxf wrote:
On 29/04/2026 10:25 am, Krishna Myneni wrote:
On 4/28/26 6:40 AM, peter wrote:
On Mon, 27 Apr 2026 17:39:11 -0500...
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
I was just looking for my IEEE 754 documentation, but I think you are
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ +NAN -NAN F= -> true }t
t{ F=ZERO F=-ZERO F= -> true }t
How is your F= defined?
I see that it returns true for comparing two nans.
Shouldn't that return false in IEEE fp math?
BR
Peter
correct that +NAN should not equal itself or -NAN, since the equality
comparison is not valid for NANs.
I am using the x87 FCOMP instruction, which I expected to have IEEE-
compatible behavior. Will need to look closer at this.
I used FCOMP and got the expected results.
\ fsp points to separate f/p stack in memory
label tst
  addr fsp ) di mov
  qword 1 floats [di] fld qword 0 [di] fld fcompp
  ax fstsw st(0) fstp 2 floats # addr fsp ) add
  41 # ah and bx bx sub cl ah cmp 1 $ jnz bx dec
1 $: bx push next
end-code
code F< ( r1 r2 -- flag ) 00 # cl mov tst ju end-code
code F> ( r1 r2 -- flag ) 01 # cl mov tst ju end-code
code F= ( r1 r2 -- flag ) 40 # cl mov tst ju end-code
+NAN +NAN F= . 0Â ok
+NAN -NAN F= . 0Â ok
Thank you. There is likely a mistake in handling the flags from FCOMP
for this case.
=) for correct comparisons with NAN and fixing the logic as needed.I'm also writing the trivial tests to check for ieee-compliant
You may want to check the behavior of FLOOR and FCEIL with IEEE special values, if your Forth system supports them. The following code should...
run on both 32-bit and 64-bit Forth systems, with or without a separate
fp stack. Some of the tests may be redundant.
--
KM
\ ============
\ Requires ttester.4th
DECIMAL
0e fconstant F=ZERO
HEX
\ Make an IEEE 754 double precision floating point value from
\ the specified bits for the sign, binary fraction, and exponent.
\ Return the fp value and error code with the following meaning:
\Â Â 0Â no error
\Â Â 1Â exponent out of range
\Â Â 2Â fraction out of range
t{ +NAN -NAN F= -> true }t
t{ -NAN FLOOR -NAN F= -> true }t
t{ -NAN FLOOR +NAN F= -> true }t
t{ +NAN FLOOR -NAN F= -> true }t
t{ +NAN FLOOR +NAN F= -> true }t
t{ -NAN FCEIL -NAN F= -> true }t
t{ -NAN FCEIL +NAN F= -> true }t
t{ +NAN FCEIL -NAN F= -> true }t
t{ +NAN FCEIL +NAN F= -> true }t
On 4/27/26 5:39 PM, Krishna Myneni wrote:
...
t{ -NAN FLOOR -NAN F= -> false }t
t{ -NAN FLOOR +NAN F= -> false }t
t{ +NAN FLOOR -NAN F= -> false }t
t{ +NAN FLOOR +NAN F= -> false }t
t{ -NAN FCEIL -NAN F= -> false }t
t{ -NAN FCEIL +NAN F= -> false }t
t{ +NAN FCEIL -NAN F= -> false }t
t{ +NAN FCEIL +NAN F= -> false }t
On 4/30/26 4:40 AM, Krishna Myneni wrote:
On 4/27/26 5:39 PM, Krishna Myneni wrote:
...
Just realized that the following tests are doing nothing more than
testing F= rather than testing FLOOR and FCEIL. In order to test that
FLOOR and FCEIL are returning a valid NAN, one should check the bit
pattern against any valid representation of a NAN.
t{ -NAN FLOOR -NAN F= -> false }t
t{ -NAN FLOOR +NAN F= -> false }t
t{ +NAN FLOOR -NAN F= -> false }t
t{ +NAN FLOOR +NAN F= -> false }t
t{ -NAN FCEIL -NAN F= -> false }t
t{ -NAN FCEIL +NAN F= -> false }t
t{ +NAN FCEIL -NAN F= -> false }t
t{ +NAN FCEIL +NAN F= -> false }t
Meaningful tests for FLOOR and FCEIL may be done with the word FNAN?
which checks for any valid representation of NAN. Thus the tests above should be replaced by
t{ -NAN FLOOR FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
t{ -NAN FCEIL FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
The word FNAN? is defined below. Your system must provide the following words:
L! ( n addr -- ) \ perform a 32-bit store to addr
UL@ ( addr -- u ) \ perform an unsigned 32-bit fetch from addr
For 32-bit systems L! and UL@ are simply ! and @ .
64-bit systems will need to provide these words intrinsically.
The revised test code is given below.
--
KM
\ ============
\ Requires ttester.4th
DECIMAL
1 cells 4 < Abort" Tests not available for cell size < 32 bits"
1 cells 8 = constant 64-bit?
\ fetch double float onto the data stack for comparison
64-bit? [IF]
: fetch-df ( addr -- u ) @ ;
: equal-df = ; \ bitwise equivalence
[ELSE]
: fetch-df ( addr -- ud ) 2@ ;
: equal-df d= ; \ bitwise equivalence
[THEN]
0e fconstant F=ZERO
HEX
\ Make an IEEE 754 double precision floating point value from
\ the specified bits for the sign, binary fraction, and exponent.
\ Return the fp value and error code with the following meaning:
\ 0 no error
\ 1 exponent out of range
\ 2 fraction out of range
fvariable temp
: MAKE-IEEE-DFLOAT ( signbit udfraction uexp -- r nerror )
dup 800 u< invert IF 2drop 2drop F=ZERO 1 EXIT THEN
14 lshift 3 pick 1F lshift or >r
dup 100000 u< invert IF
r> 2drop 2drop F=ZERO 2 EXIT
THEN
r> or [ temp 4 + ] literal L! temp L!
drop temp df@ 0 ;
: FSIGNBIT ( F: r -- ) ( -- minus? )
temp df! [ temp 4 + ] literal UL@ 80000000 and 0<> ;
: FEXPONENT ( F: r -- ) ( -- u )
temp df! [ temp 4 + ] literal UL@ 14 rshift 7FF and ;
: FFRACTION ( F: r -- ) ( -- ud )
temp df! temp UL@ [ temp 4 + ] literal UL@ 000FFFFF and ;
: FINITE? ( F: r -- ) ( -- [normal|subnormal]? ) fexponent 7FF <> ;
: FNORMAL? ( F: r -- ) ( -- normal? ) fexponent 0<> ;
: FSUBNORMAL? ( F: r -- ) ( -- subnormal? ) fexponent 0= ;
: FINFINITE? ( F: r -- ) ( -- [+/-]Inf? )
finite? invert ;
: FNAN? ( F: r -- ) ( -- nan? )
fdup FEXPONENT 7FF = >r FFRACTION D0= invert r> and ;
\ Constants representing -0e -INF +INF -NAN +NAN
true 0 0 0 make-ieee-dfloat [IF] fdrop [ELSE] fconstant F=-ZERO [THEN]
true 0 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -INF [THEN]
[DEFINED] -INF [IF] -INF fnegate fconstant +INF [THEN]
true 1 0 7FF make-ieee-dfloat [IF] fdrop [ELSE] fconstant -NAN [THEN] [DEFINED] -NAN [IF] -NAN fnegate fconstant +NAN [THEN]
DECIMAL
: FCEIL ( F: r1 -- r2 ) FNEGATE FLOOR FNEGATE ;
\ Testing F= for positive and negative special values
t{ +INF -INF F= -> false }t
t{ F=ZERO F=-ZERO F= -> true }t
t{ +NAN -NAN F= -> false }t
\ Verify FNAN? recognizes both +NAN and -NAN as a NAN
t{ +NAN FNAN? -> true }t
t{ -NAN FNAN? -> true }t
\ Testing bitwise inequality of positive and negative special values
create r1 8 allot \ allot dfloat
create r2 8 allot \ allot dfloat
t{ F=ZERO r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
t{ +INF r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
t{ +NAN r1 DF! -> }t
t{ -NAN r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> false }t
TESTING FLOOR with IEEE 754 Special values
t{ F=ZERO FLOOR r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ F=-ZERO FLOOR r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -INF FLOOR r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ +INF FLOOR r1 DF! -> }t
t{ +INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -NAN FLOOR FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
t{ 0.1e FLOOR r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -0.1e FLOOR r1 DF! -> }t
t{ -1.0e r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
TESTING FCEIL with IEEE 745 values
t{ F=ZERO FCEIL r1 DF! -> }t
t{ F=ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ F=-ZERO FCEIL r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -INF FCEIL r1 DF! -> }t
t{ -INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ +INF FCEIL r1 DF! -> }t
t{ +INF r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -NAN FCEIL FNAN? -> true }t
t{ +NAN FCEIL FNAN? -> true }t
t{ 0.1e FCEIL r1 DF! -> }t
t{ 1.0e r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
t{ -0.1e FCEIL r1 DF! -> }t
t{ F=-ZERO r2 DF! -> }t
t{ r1 fetch-df r2 fetch-df equal-df -> true }t
\ end of tests
\ ============
On Thu, 30 Apr 2026 05:37:13 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 4/30/26 4:40 AM, Krishna Myneni wrote:
On 4/27/26 5:39 PM, Krishna Myneni wrote:
...
Just realized that the following tests are doing nothing more than
testing F= rather than testing FLOOR and FCEIL. In order to test that
FLOOR and FCEIL are returning a valid NAN, one should check the bit
pattern against any valid representation of a NAN.
t{ -NAN FLOOR -NAN F= -> false }tMeaningful tests for FLOOR and FCEIL may be done with the word FNAN?
t{ -NAN FLOOR +NAN F= -> false }t
t{ +NAN FLOOR -NAN F= -> false }t
t{ +NAN FLOOR +NAN F= -> false }t
t{ -NAN FCEIL -NAN F= -> false }t
t{ -NAN FCEIL +NAN F= -> false }t
t{ +NAN FCEIL -NAN F= -> false }t
t{ +NAN FCEIL +NAN F= -> false }t
which checks for any valid representation of NAN. Thus the tests above
should be replaced by
t{ -NAN FLOOR FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
t{ -NAN FCEIL FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
The word FNAN? is defined below. Your system must provide the following
words:
L! ( n addr -- ) \ perform a 32-bit store to addr
UL@ ( addr -- u ) \ perform an unsigned 32-bit fetch from addr
For 32-bit systems L! and UL@ are simply ! and @ .
64-bit systems will need to provide these words intrinsically.
The revised test code is given below.
Now the test cases run without error on both lxf and lxf64
In lxf64 ABORT" is a compile only word so I just commented out that
I have L@ for zero extended fetch and <L@ for sign extended.
That works well also for C@ and <C@ ( and W@, <W@)
I had already FNAN? defined as : FNAN? FDUP F<> ;
Thanks for your test program I found that I had misspelled FCEIL
It was named FCIEL, probably after the Italian word cielo (sky)
( I live since more that 30 years in Italy)
More importantly I found that f< and friends behaved differently
when they were followed by an IF, not always treating nans correctly
There is a memory
words proposal that deals with words like UL@ etc. but I'm not sure
where it is in the pipeline right now. Gforth also uses UL@ for unsigned >32-bit fetch. kForth uses UL@ and SL@ for unsigned and signed,
respectively, and we have UW@ and SW@ -- the mnemonic prefix helps me to
use the correct version, especially given how different Forth systems >treated W@ as unsigned in some systems and signed in others.
On 4/30/26 8:55 AM, peter wrote:
On Thu, 30 Apr 2026 05:37:13 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 4/30/26 4:40 AM, Krishna Myneni wrote:
On 4/27/26 5:39 PM, Krishna Myneni wrote:
...
Just realized that the following tests are doing nothing more than
testing F= rather than testing FLOOR and FCEIL. In order to test that
FLOOR and FCEIL are returning a valid NAN, one should check the bit
pattern against any valid representation of a NAN.
t{ -NAN FLOOR -NAN F= -> false }tMeaningful tests for FLOOR and FCEIL may be done with the word FNAN?
t{ -NAN FLOOR +NAN F= -> false }t
t{ +NAN FLOOR -NAN F= -> false }t
t{ +NAN FLOOR +NAN F= -> false }t
t{ -NAN FCEIL -NAN F= -> false }t
t{ -NAN FCEIL +NAN F= -> false }t
t{ +NAN FCEIL -NAN F= -> false }t
t{ +NAN FCEIL +NAN F= -> false }t
which checks for any valid representation of NAN. Thus the tests above
should be replaced by
t{ -NAN FLOOR FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
t{ -NAN FCEIL FNAN? -> true }t
t{ +NAN FLOOR FNAN? -> true }t
The word FNAN? is defined below. Your system must provide the following
words:
L! ( n addr -- ) \ perform a 32-bit store to addr
UL@ ( addr -- u ) \ perform an unsigned 32-bit fetch from addr
For 32-bit systems L! and UL@ are simply ! and @ .
64-bit systems will need to provide these words intrinsically.
The revised test code is given below.
Now the test cases run without error on both lxf and lxf64
In lxf64 ABORT" is a compile only word so I just commented out that
I have L@ for zero extended fetch and <L@ for sign extended.
That works well also for C@ and <C@ ( and W@, <W@)
I had already FNAN? defined as : FNAN? FDUP F<> ;
Thanks for your test program I found that I had misspelled FCEIL
It was named FCIEL, probably after the Italian word cielo (sky)
( I live since more that 30 years in Italy)
More importantly I found that f< and friends behaved differently
when they were followed by an IF, not always treating nans correctly
Great. Needless to say the exercise helped me as well. There is a memory words proposal that deals with words like UL@ etc. but I'm not sure
where it is in the pipeline right now. Gforth also uses UL@ for unsigned 32-bit fetch. kForth uses UL@ and SL@ for unsigned and signed,
respectively, and we have UW@ and SW@ -- the mnemonic prefix helps me to
use the correct version, especially given how different Forth systems treated W@ as unsigned in some systems and signed in others.
My definition of FNAN? goes by the ieee 754 definition of what
constitutes a NAN, but there may be no practical difference in the two definitions.
I'm guessing you have a flag use conflict if F< behaves differently when
it is followed by an IF.
I need to review all of the IEEE fp test code written by the late David
N Williams -- I would like to fill in any missing pieces.
Cheers,
Krishna
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
There is a memory
words proposal that deals with words like UL@ etc. but I'm not sure
where it is in the pipeline right now. Gforth also uses UL@ for unsigned >32-bit fetch. kForth uses UL@ and SL@ for unsigned and signed, >respectively, and we have UW@ and SW@ -- the mnemonic prefix helps me to >use the correct version, especially given how different Forth systems >treated W@ as unsigned in some systems and signed in others.
The current state of the proposal is:
https://forth-standard.org/proposals/special-memory-access-words?hideDiff#reply-1531
The state is that the committee likes the proposal and I have to find
the time to do a reference implementation and tests to complete it,
then it should progress further.
As for sw@ and uw@, I used to advocate that approach and precomposed
words in general, but once you add byte-order variations, you get a
lot of words; with precomposed words the W set alone would consist of:
be-sw@ le-sw@ sw@ be-uw@ le-uw@ uw@ be-w! le-w! w!
compared to
w@ w! wbe wle w>s
in the proposal. Moreover, once you add stuff like "w,", you either
need precomposed versions of that, too, or you need to introduce wbe
and wle anyway.
So eventually I became convinced of the decomposed approach. W@
produces an zero-extended (unsigned) result in the proposal.
- anton
Whatever the standard will be I will continue with <w@, <C@ etc
They are a great visual help to see the intent.
They are used only in the internals of the compilers and decompilers
and will compile to just one cpu opcode
For the byte order I agree with the proposal be-sw@ looks horrible
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
There is a memory
words proposal that deals with words like UL@ etc. but I'm not sure
where it is in the pipeline right now. Gforth also uses UL@ for unsigned
32-bit fetch. kForth uses UL@ and SL@ for unsigned and signed,
respectively, and we have UW@ and SW@ -- the mnemonic prefix helps me to
use the correct version, especially given how different Forth systems
treated W@ as unsigned in some systems and signed in others.
The current state of the proposal is:
https://forth-standard.org/proposals/special-memory-access-words?hideDiff#reply-1531
The state is that the committee likes the proposal and I have to find
the time to do a reference implementation and tests to complete it,
then it should progress further.
As for sw@ and uw@, I used to advocate that approach and precomposed
words in general, but once you add byte-order variations, you get a
lot of words; with precomposed words the W set alone would consist of:
be-sw@ le-sw@ sw@ be-uw@ le-uw@ uw@ be-w! le-w! w!
compared to
w@ w! wbe wle w>s
in the proposal. Moreover, once you add stuff like "w,", you either
need precomposed versions of that, too, or you need to introduce wbe
and wle anyway.
So eventually I became convinced of the decomposed approach. W@
produces an zero-extended (unsigned) result in the proposal.
- anton
peter <peter.noreply@tin.it> writes:
Whatever the standard will be I will continue with <w@, <C@ etc
They are a great visual help to see the intent.
They are used only in the internals of the compilers and decompilers
and will compile to just one cpu opcode
gforth-fast compiles "w@ w>s" into one native instruction, too:
: <w@ w@ w>s ; ok
IIUC, to do an explicit signed word fetch on little endian system one
would write using the current proposal
W@ WLE W>S
and on a little-endian system, one could get away with writing
W@ W>S
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
IIUC, to do an explicit signed word fetch on little endian system one
would write using the current proposal
W@ WLE W>S
If you have a 16-bit signed number stored in little-endian format,
that's the way to get it on the stack, whether your hardware is
little-endian or big-endian.
and on a little-endian system, one could get away with writing
W@ W>S
If you have a 16-bit signed number stored in the byte order of your
hardware, that's the way to fetch it.
...
I would prefer W@ and similar words which do unsigned fetch be prefixed
with 'U', because some systems have used W@ for unsigned and some for
signed word fetch (LMI 80386 UR/Forth and kForth-32/64).
I would prefer W@ and similar words which do unsigned fetch be prefixed
with 'U', because some systems have used W@ for unsigned and some for
signed word fetch (LMI 80386 UR/Forth and kForth-32/64).
Using the U prefix prevents breaking of older code and keeps the number
of memory words the same as in the current proposal. The 'U' prefix also
has the advantage of providing a hint to the programmer, helping to
prevent programming mistakes.
The rest of the proposal is fine with me.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
I would prefer W@ and similar words which do unsigned fetch be prefixed
with 'U', because some systems have used W@ for unsigned and some for
signed word fetch (LMI 80386 UR/Forth and kForth-32/64).
Using the U prefix prevents breaking of older code and keeps the number
of memory words the same as in the current proposal. The 'U' prefix also
has the advantage of providing a hint to the programmer, helping to
prevent programming mistakes.
The rest of the proposal is fine with me.
Ideally you add this as a reply to https://forth-standard.org/proposals/special-memory-access-words?hideDiff#reply-1531
(plus the additional information which systems have sign-extending
W@), so others interested in the proposal can see it and comment on
it, and so that I remember this point when I find the the time to work
on the proposal.
On 4/29/26 8:30 AM, Krishna Myneni wrote:...
On 4/28/26 8:20 PM, dxf wrote:
I used FCOMP and got the expected results.
\ fsp points to separate f/p stack in memory
label tst
  addr fsp ) di mov
  qword 1 floats [di] fld qword 0 [di] fld fcompp
  ax fstsw st(0) fstp 2 floats # addr fsp ) add
  41 # ah and bx bx sub cl ah cmp 1 $ jnz bx dec
1 $: bx push next
end-code
code F< ( r1 r2 -- flag ) 00 # cl mov tst ju end-code
code F> ( r1 r2 -- flag ) 01 # cl mov tst ju end-code
code F= ( r1 r2 -- flag ) 40 # cl mov tst ju end-code
+NAN +NAN F= . 0Â ok
+NAN -NAN F= . 0Â ok
Thank you. There is likely a mistake in handling the flags from FCOMP
for this case.
There was indeed a problem with my logic for the status bits from the
x87 fpu. They logic was not correct for handling the status word's
condition bits C0 -- C3 correctly in the case of NANs. I believe
comparisons with all other IEEE special values work, but I'm not sure we have sufficient tests yet to ensure this.
I am presently reviewing the other floating point comparisons (F< F> F<= F>=) for correct comparisons with NAN and fixing the logic as needed.
I'm also writing the trivial tests to check for ieee-compliant
comparisons with NANs.
kForth-32/64 will be patched by the end of the week.
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,116 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 87:51:31 |
| Calls: | 14,305 |
| Files: | 186,338 |
| D/L today: |
1,222 files (386M bytes) |
| Messages: | 2,525,536 |