diff options
-rw-r--r-- | README.win32 | 8 | ||||
-rw-r--r-- | pp.c | 35 | ||||
-rw-r--r-- | pp_hot.c | 7 | ||||
-rw-r--r-- | sv.c | 7 | ||||
-rw-r--r-- | win32/win32.h | 5 |
5 files changed, 55 insertions, 7 deletions
diff --git a/README.win32 b/README.win32 index 4815a32add..066a6dc752 100644 --- a/README.win32 +++ b/README.win32 @@ -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 @@ -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; } } @@ -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; } } @@ -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) diff --git a/win32/win32.h b/win32/win32.h index e56c4df13d..7be8482ce4 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -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 */ |