Running the following test program produces an assertion failure in
gm2's Modula-2 floating-point output functions that wipes the stack:
% cat TestNaNOutput.mod
MODULE TestNaNOutput;
FROM FpuIO IMPORT WriteLongReal;
FROM RealInOut IMPORT WriteReal, WriteShortReal;
FROM StrIO IMPORT WriteLn, WriteString;
VAR x : SHORTREAL;
xx : REAL;
xxx : LONGREAL;
BEGIN
x := 0.0 / 0.0; (* generate quiet NaN *)
WriteString ('x = ');
WriteShortReal(x, 11);
WriteLn;
xx := 0.0 / 0.0; (* generate quiet NaN *)
WriteString ('xx = ');
WriteReal(xx, 11);
WriteLn;
xxx := 0.0 / 0.0; (* generate quiet NaN *)
WriteString ('xxx = ');
WriteLongReal(xxx, 26, 20);
WriteLn
END TestNaNOutput.
Here is a run:
% gm2 -g -g3 TestNaNOutput.mod && ./a.out
../../../../gcc-14-20240114/libgm2/libm2pim/../../gcc/m2/gm2-libs/StringConvert.mod:1069:in
ToDecimalPlaces has caused assert failed
Rearranging the test program code blocks, or commenting out any two of
them, shows the same failure for all three precisions.
Here is an attempt to get a debug traceback:
% gdb a.out
...
(gdb) run
...
(gdb) where
No stack.
(gdb) quit
Here is a retry:
% gdb a.out
...
(gdb) b StringConvert.mod:1069
No source file named StringConvert.mod.
Make breakpoint pending on future shared library load? (y or [n]) y
,,,
(gdb) run
.,,
(gdb) where
#0 ToDecimalPlaces (s=0x44e050, n=6) at
../../../../gcc-14-20240114/libgm2/libm2pim/../../gcc/m2/gm2-libs/StringConvert.mod:1069
#1 0x00007ffff77aa01d in m2pim_StringConvert_LongrealToString
(x=-nan(0xc000000000000000), TotalWidth=0, FractionWidth=6)
at
../../../../gcc-14-20240114/libgm2/libm2pim/../../gcc/m2/gm2-libs/StringConvert.mod:813
#2 0x00007ffff79cde12 in m2log_RealInOut_WriteShortReal
(x=-nan(0x400000), n=11) at
../../../../gcc-14-20240114/libgm2/libm2log/../../gcc/m2/gm2-libs-log/RealInOut.mod:220
#3 0x000000000040250d in _M2_TestNaNOutput_init (argc=1,
argv=0x7fffffffce88, envp=0x7fffffffce98) at TestNaNOutput.mod:21
#4 0x00007ffff779e75c in m2pim_M2Dependent_ConstructModules
(applicationmodule=<optimized out>, libname=<optimized out>,
overrideliborder=<optimized out>, argc=1, argv=0x7fffffffce88,
envp=0x7fffffffce98) at
../../../../gcc-14-20240114/libgm2/libm2pim/../../gcc/m2/gm2-libs/M2Dependent.mod:823
#5 0x0000000000402b44 in _M2_init (argc=1, argv=0x7fffffffce88,
envp=0x7fffffffce98) at TestNaNOutput.mod:1
#6 0x0000000000402baa in main (argc=1, argv=0x7fffffffce88,
envp=0x7fffffffce98) at TestNaNOutput.mod:1
Similar tests with Infinity instead of NaN (just replace the 0.0
numerator with 1.0 in the above test program) show the same failure.
It is IMPERATIVE that IEEE 754 floating-point arithmetic, which is now
44 years old in hardware (the first hardware implementation appeared
in the Intel 8087 chip appeared in 1980), and implemented on tens of
billions of computing devices, be properly supported in all
programming languages.
In particular, this means that signed Infinity, signed zero, and quiet
and signalling NaNs MUST be treated as normal values that can occur in
computations, and must be able to be both input and output in numeric
data streams.
NaN payloads should be supported as well, such as this example from my
hoc programs:
hoc> x = qnan("0xfeedfacedeadcafe")
hoc> x
+QNaN
hoc> printf("%.g\n", x)
qnan(0x1facedeadcafe)
Payloads can be used to encode variable addresses, indicators of
missing data, error codes, or anything else that the programmer finds
useful: only the top two significand bits are reserved for
distinguishing between the two kinds of NaN, and Infinity. The
remaining bits are available for any user-defined payload.
-------------------------------------------------------------------------------
- Nelson H. F. Beebe Tel: +1 801 581 5254 -
- University of Utah -
- Department of Mathematics, 110 LCB Internet e-mail: beebe@math.utah.edu -
- 155 S 1400 E RM 233 beebe@acm.org beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------