Author: Kevin B. Kenny <[email protected]>
State: Draft
Type: Project
Vote: Pending
Created: 18 October 2018
Post-History:
Tcl-Version: 9.1
Keywords: Tcl, floating point, NaN, not a number
Tcl-Branch: tip-520
Abstract
This TIP proposes that the special floating point constants NaN
,
±NaN
, and [±]NaN(
hex)
be accepted in any context where
other floating point constants may appear. This change has the effect
of changing Tcl from 'signalling NaN' semantics (where floating-point
exceptions are errors) to 'quiet NaN' semantics (where floating-point
exceptions return the constant, NaN
, and operations where one of the
operands is NaN
propagate the NaN
to their results).
Background
Since Tcl 8.5, [TIP 132] Tcl has had the capability to
recognize the special IEEE floating point constants, Inf
(representing an infinity or an overflow) and NaN
(representing a
value that is 'Not a Number', ordinarily the result of some sort of
floating point exception). Infinities are now accepted on an equal
footing with other floating point constants; they can be passed
anywhere that such a constant can appear, and they follow IEEE 754
rules for arithmetic.
The constant, NaN
is different. If a floating-point expression
yields a NaN
, or if Tcl_GetDoubleFromObj
receives such a
constant, the system treats the condition as an error, 'domain error:
argument not in valid range
'.
This behaviour was specified explicitly in paragraph 5 of TIP 132:
The input and output conversions shall allow for the IEEE special values
+Inf
,-Inf
, andNaN
(and for denormalized numbers). The [expr] command shall be changed to allow +Inf and -Inf as the result of an expression;NaN
shall still cause an error.Tcl_GetDoubleFromObj
shall treat+Inf
and-Inf
as it does any ordinary floating point number, and return an error forNaN
.
This sort of handling was adopted because at the time, NaN
was a
relatively new thing, and programmers were suspicious of it. Many
believed that if operations like 0./0. or asin(2.0) were allowed
to return NaN
rather than throwing an immediate error, debugging
would be greatly complicated, to very little benefit. (The personal
recollection of the author of this TIP was that even infinities were
tough to sell, for much the same reason.)
Since then, NaN
values have been much more broadly accepted. Most
C compilers have quiet-NaN
behaviour by default; a floating-point
exception returns NaN
rather than raising SIGFPE
. The world
seems to have accepted William Kahan's remarks:
My thesis is that exceptions are not errors unless they are handled badly. Exceptions are opportunities for extra computation.... An exception is an event for which any policy you choose in advance will subsequently be found disadvantageous for somebody who will then, for good reason, take exception to the policy.
This change in sentiment was underlined for the author of this TIP
by the fact that in no fewer than three separate conversations at the
2018 Tcl/Tk Conference, he was approached with queries about NaN
handling. An increasing number of users are dealing with external systems
that use NaN
to indicate a missing value in a data set, and
need NaN
to be passed in and out gracefully.
Proposal
Tcl's expression evaluator, and the functions in ::tcl::mathfunc
and ::tcl::mathop
, shall be changed to allow NaN
values to
be returned from floating-point expressions. (This change has already
been available in the source code for a long time, and can be enabled
by adding -DACCEPT_NAN
to the compilation options.)
The math functions max
and min
shall be defined so that if any
argument to the function is NaN
, the output shall be NaN
.
Functions requiring integers, functions coercing 'double' values to
integers (int
, wide
, round
, entier
), and the isqrt
function shall continue to throw errors when presented with NaN
(there seems to be nothing sensible to do with these cases).
The C interface Tcl_GetDoubleFromObj
shall be modified to accept
NaN's without thowing errors.
The implementations of the lsort -real
and lsearch -real
commands
shall be modified to continue to throw errors if a NaN
is
encountered in either the list or the search pattern. Since NaN
is
unordered with respect to any floating point constant, there is no
correct behaviour for these commands when asked to sort a list
containing one.
Reference Implementation
Most of the implementation has been in the code base for along time,
albeit hidden, under the -DACCEPT_NAN
compilation option.
A few changes (updates to the test suite to reflect the new default;
update to Tcl_GetDoubleFromObj
; changes to max
and min
)
still need to be made; the link to the implementation branch will
be added to this TIP.
Unresolved Concerns
The change to Tcl_GetDoubleFromObj
, alone among the changes outlined
in this proposal, may need to be delayed until Tcl 9. It introduces a
subtle incompatibility in C code in that quiet NaN
values can be
returned to a caller that does not expect them. In particular, the
author has not yet investigated whether Tk methods such as xview
,
yview
, xscroll
, and yscroll
will survive such exceptional
arguments without throwing SIGFPE
. These are invalid arguments -
the author is willing to accept almost any behaviour that does not
render the UI unusable or abort the process, but we need to verify
that .my.widget yview NaN
does not invoke nasal daemons.