RE: [PATCH, no, really!] Re: [perl #38779] NAN's on Win32
Jan Dubois [Wed, 22 Mar 2006 22:49:11 +0000 (14:49 -0800)]
From: "Jan Dubois" <jand@ActiveState.com>
Message-ID: <060201c64e45$e4ca7020$2217a8c0@candy>

Also, back out change #27567.
p4raw-link: @27567 on //depot/perl: 9bf76a6a2fc16ab628a46452e34352d3e3d71674

p4raw-id: //depot/perl@27576

README.win32
pp.c
pp_hot.c
sv.c
win32/win32.h

index 4815a32..066a6dc 100644 (file)
@@ -859,12 +859,6 @@ Thus, signals may work only for simple things like setting a flag
 variable in the handler.  Using signals under this port should
 currently be considered unsupported.
 
-Numeric comparisons involving "Not a Number" (NaN, an IEEE floating point
-feature) will give incorrect results if you build with Visual C++ Version 6
-or earlier -- see I<Floating-Point Comparison> in
-L<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndeepc/html/deep05282002.asp>
-for details. If possible, you should build using a later version of VC++.
-
 Please send detailed descriptions of any problems and solutions that
 you may find to E<lt>F<perlbug@perl.org>E<gt>, along with the output
 produced by C<perl -V>.
@@ -915,6 +909,6 @@ Win9x support was added in 5.6 (Benjamin Stuhl).
 
 Support for 64-bit Windows added in 5.8 (ActiveState Corp).
 
-Last updated: 22 March 2006
+Last updated: 30 September 2005
 
 =cut
diff --git a/pp.c b/pp.c
index 6b3ead8..99f0b06 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1714,8 +1714,15 @@ PP(pp_lt)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left < right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn < value));
+#endif
       RETURN;
     }
 }
@@ -1790,8 +1797,15 @@ PP(pp_gt)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left > right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn > value));
+#endif
       RETURN;
     }
 }
@@ -1866,8 +1880,15 @@ PP(pp_le)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left <= right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn <= value));
+#endif
       RETURN;
     }
 }
@@ -1942,8 +1963,15 @@ PP(pp_ge)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left >= right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn >= value));
+#endif
       RETURN;
     }
 }
@@ -2011,8 +2039,15 @@ PP(pp_ne)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETYES;
+      SETs(boolSV(left != right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn != value));
+#endif
       RETURN;
     }
 }
index c34fb90..3b4d8ed 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -363,8 +363,15 @@ PP(pp_eq)
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left == right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn == value));
+#endif
       RETURN;
     }
 }
diff --git a/sv.c b/sv.c
index cb8d217..d8b4d74 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1895,6 +1895,13 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
           certainly cast into the IV range at IV_MAX, whereas the correct
           answer is the UV IV_MAX +1. Hence < ensures that dodgy boundary
           cases go to UV */
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+       if (Perl_isnan(SvNVX(sv))) {
+           SvUV_set(sv, 0);
+           SvIsUV_on(sv);
+       }
+       else
+#endif
        if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
            SvIV_set(sv, I_V(SvNVX(sv)));
            if (SvNVX(sv) == (NV) SvIVX(sv)
index e56c4df..7be8482 100644 (file)
@@ -210,6 +210,11 @@ typedef unsigned short     mode_t;
 
 #define isnan          _isnan
 
+#if _MSC_VER < 1300
+/* VC6 has broken NaN semantics: NaN == NaN returns true instead of false */
+#define NAN_COMPARE_BROKEN 1
+#endif
+
 #endif /* _MSC_VER */
 
 #ifdef __MINGW32__             /* Minimal Gnu-Win32 */