Tcl Source Code

View Ticket
Login
Ticket UUID: 761471
Title: INST_EQ issues with NaN
Type: Bug Version: obsolete: 8.5a2
Submitter: dgp Created on: 2003-06-26 21:45:01
Subsystem: 47. Bytecode Compiler Assigned To: dgp
Priority: 9 Immediate Severity:
Status: Closed Last Modified: 2006-03-23 23:40:37
Resolution: Wont Fix Closed By: dgp
    Closed on: 2006-03-23 16:40:37
Description:
This is inconsistent:

% set x NaN; expr {$x == NaN} 
1
% expr {$x == NaN} 
0

They are different because the
first case follows an optimization
in INST_EQ that a Tcl_Obj will
be == to itself.

The second case actually flows
through to a C-level comparison
of two NaN doubles, and at least
on this platform, the result is false.
User Comments: dgp added on 2006-03-23 23:40:36:
Logged In: YES 
user_id=80530


marked expr-22.9 nonPortable
for 8.4.13 release.

dgp added on 2006-03-10 22:56:48:
Logged In: YES 
user_id=80530


let's get off the fence 
for 8.4.13.  Either fix
this, or silence the test
with a "knownBug" constraint.

dgp added on 2005-11-05 03:28:48:
Logged In: YES 
user_id=80530

if you mean that this will
become "Won't Fix" on
8.4, then I suggest silencing
test expr-22.9 on that branch.

kennykb added on 2005-11-05 03:18:56:
Logged In: YES 
user_id=99768

Don, should we close this as 'fixed in 8.5' and leave
8.4 doing whatever it is that 8.4 does?

matzek added on 2005-03-04 00:29:25:
Logged In: YES 
user_id=330806

Another report:
expr-22.9 is broken on HP-UX 64 bit
-11.23 on IA64 using cc: HP aC++/ANSI C B3910B A.05.52 [Sep
05 2003]
-11.00 on PA-Risc using cc (HP C/ANSI C B3901BA B.11.02.02)

kind regards
-- Matthias Kraft

dkf added on 2004-11-24 17:13:10:
Logged In: YES 
user_id=79902

expr-22.9 postdates 8.4.7

sprkyflshpnts added on 2004-11-24 01:47:12:
Logged In: YES 
user_id=854097

expr-22.9 fails for me on WinXP SP2 using VC++ .NET 2003
(Tcl 8.4.8).  It worked for me in Tcl 8.4.7.

das added on 2004-11-19 21:19:09:
Logged In: YES 
user_id=90580

re 1069261:
note that expr-22.9 suceeds on mac os x 10.3 and on OpenBSD 3.4 and 
NetBSD 1.6.1.
only macosx 10.2 and FreeBSD 4.8 are broken...

msofer added on 2004-11-19 16:20:08:
Logged In: YES 
user_id=148712

oh my - is bsd also borken_stiff? See Bug 1069261

msofer added on 2004-11-13 04:40:19:
Logged In: YES 
user_id=148712

Note that  (at the top)

#ifdef BORKEN_STIFF_COMPILER
#define IS_NAN(x) _isnan(x)
#else
#define IS_NAN(x) ((x) != (x))
#endif

and the code below at line 3383 would fix the issue of msvc
not doing the right comparisons for NaN, but does not touch
the other brokenness in win: that strtod() does not
recognize "NaN" as a double. 

FWIW, that can be written simpler as

#ifdef BORKEN_STIFF_COMPILER
    if (IS_NAN(d1) || IS_NAN(d2)) {
        iResult = (*pc == INST_NEQ);
        goto foundResult;
    }
#endif

kennykb added on 2004-11-12 06:02:43:
Logged In: YES 
user_id=99768

Miguel suggests:
#ifdef BORKEN_STIFF_COMPILER
if (IS_NAN(d1) || IS_NAN(d2)) {
    if(*pc == INST_NEQ) {
        iResult = 1;
    } else {
        iResult = 0;
    }
    goto foundResult;
}
#endif
near line 3383 in tclExecute.c

kennykb added on 2004-11-06 03:21:51:

File Added - 107751: expr27.tcl

Logged In: YES 
user_id=99768

For your consideration, I attach a proposed set of test vectors
for verifying IEEE 754 comparison semantics.

msofer added on 2004-11-05 23:39:01:
Logged In: YES 
user_id=148712

Can we then, for VC only,
  #define IS_NAN(x) _isnan(x)
in tclExecute.c and have this stuff fixed?

kennykb added on 2004-11-05 23:34:28:
Logged In: YES 
user_id=99768

Ugh.  I just looked this one up.

VC++6 is not IEEE-754 compliant with respect to NaN
comparisons.  (I disassembled the object code - and
verified this.  It simply doesn't check for "unordered"
in the result word.  VC.NET allegedly fixes this - see
for example

http://msdn.microsoft.com/library/en-us/dndeepc/html/deep05282002.asp

Where does that leave us?  We probably need to
do explicit tests for the "special values" when
compiling on VC++6.  There are tests available in
<float.h>:

_finite(x) - Returns TRUE for ordinary and subnormal
values, FALSE for Inf and NaN

_isnan(x) - Returns TRUE for NaN, FALSE for
everything else.

_fpclass(x) - Returns a value that classifies a given
FP number.  See
http://msdn.microsoft.com/library/en-us/vccore98/HTML/_crt__fpclass.asp
for the constants.

msofer added on 2004-11-05 16:32:27:
Logged In: YES 
user_id=148712

Note that thismeans that NaN handling in Tcl/VC has been
broken for a while - our detection is done by the IS_NAN
macro in tclExecute.c, which tests for exactly this.

Just wild guessing here - maybe there is some compilation
flag required to get proper IEEE handling, disabled by
default 'cause it gets slower? 
One possible solution would be to #define IS_NAN
conditionally on the compiler being used. Maybe there is an
equivalent function in VC that could be called? 

Worst case - if the VC bug is unfixable, we should either
disable the test on that platform, or maybe pay a heavy cost
in double handling and try detecting NaN on the double's
string rep?

Assigning to Kevin as our resident VC guru ...

dkf added on 2004-11-05 16:10:51:
Logged In: YES 
user_id=79902

This is a bug in VC's floating-point number handling.

wildcard_25 added on 2004-11-05 09:07:43:
Logged In: YES 
user_id=596509

Tk: v8.5a2
OS: WinXPsp2
Head: 04-11-04
Built with makefile.vc using VC7.1

==== expr-22.9 non-numeric floats: shared object equality 
and NaN FAILED
==== Contents of test case:

    set x NaN
    expr {$x == $x}

---- Result was:
1
---- Result should have been (exact matching):
0
==== expr-22.9 FAILED

dkf added on 2004-11-02 22:47:39:
Logged In: YES 
user_id=79902

Great.  That gives virtually the original functionality and
yet gets the NaN nasty right. :^)

Fixed in HEAD and 8.4 branch.

msofer added on 2004-11-02 02:34:49:

File Added - 107261: NaN.patch2

Logged In: YES 
user_id=148712

Patch replaced with a better one. NaN stuff is OK (shortcut
gives the same as glibc, howzzat for a criterion?). Don't
know about other "funny" values like Inf, -0, ...

msofer added on 2004-11-01 23:38:58:

File Added - 107246: NaN.patch

msofer added on 2004-11-01 23:38:56:
Logged In: YES 
user_id=148712

Attaching a patch with my optimisation: it does seem to
work. At least 
 % set x NaN; expr {$x == NaN}
 0

dkf added on 2004-11-01 21:42:44:
Logged In: YES 
user_id=79902

Your optimization won't work.  You simply can't rely on NaN
being of tclDoubleType and the cost of determining the cases
where the comparison is actually safe is rather too high. :^(

At least in the equal object case, any through-string
conversions will be mostly cached... :^/

Fixed in HEAD; backport candidate or shall we not bother
given how few people noticed this was broken for so many years?

msofer added on 2004-11-01 19:28:27:
Logged In: YES 
user_id=148712

Suggestion for change at INST_EQ and family:

* Try first the conversion of valuePtr to numeric type (DEOPT)
* Shortcut:
       if ((valuePtr == value2Ptr) && (t1Ptr !=
&tclDoubleType)) {
             ... shortcut; jump to end
       } else if (valuePtr != value2Ptr) {
            ... convert value2Ptr
       }
       ... 

This retains the shortcut for non-doubles, and forces
doubles to go through the C library.

dkf added on 2004-11-01 18:21:29:
Logged In: YES 
user_id=79902

NaN is the only value that is not equal to itself, but it's
non-trivial to write a special test for it. I believe we
just have to deoptimize INST_EQ (though this will marginally
shorten TEBC of course.)

msofer added on 2004-10-31 02:47:29:
Logged In: YES 
user_id=148712

I did not get it, did I? Sorry ...

msofer added on 2004-10-31 02:44:21:
Logged In: YES 
user_id=148712

uhh - no, it can't be list type - it will have been
converted to a double, as == attempts numeric conversion first.

So the problem may well be that Tcl_GetDoubleFromObj is not
handling NaN correctly? Is the following correct
 % expr double(NaN)
 domain error: argument not in valid range
or should the return value be NaN?

dkf added on 2004-10-22 06:21:39:
Logged In: YES 
user_id=79902

NaN is tclDoubleType (or non-numeric; could be a list just
fine!)

AFAICT, the only way to avoid the problem is to remove the
equal-object check from the top of the INST_EQ implementation.

msofer added on 2004-03-30 04:39:24:
Logged In: YES 
user_id=148712

Is there any other exception to this? Ie, other possibility
of a Tcl_Obj not being == to itself?
If not, it coud be handled as a special case. What objtype
is NaN?

dkf added on 2004-03-30 04:06:33:
Logged In: YES 
user_id=79902

Arguably, the solution is to only do the object comparison
when not doing numeric comparison.  But figuring out which
kind of comparison to do could be expensive.  Ick.  Looks
like we'll need to deoptimise...  :-(

dkf added on 2003-06-27 15:38:59:
Logged In: YES 
user_id=79902

Another case:
  % set x NaN; expr {$x == $x}
  1
This case is *definitely* the INST_EQ opt.  The other case
in the bug report mixes it up with aggressive literal
sharing.  (Just a note that the C-level comparison result is
correct; we don't want to put in special code to make NaN
equal to itself!)

Attachments: