This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
infnan: more tests.
[perl5.git] / perl.h
diff --git a/perl.h b/perl.h
index 55b33de..8e81724 100644 (file)
--- a/perl.h
+++ b/perl.h
 #   include "config.h"
 #endif
 
-#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(_STDC_C99)
+/* NOTE 1: that with gcc -std=c89 the __STDC_VERSION__ is *not* defined
+ * because the __STDC_VERSION__ became a thing only with C90.  Therefore,
+ * with gcc, HAS_C99 will never become true as long as we use -std=c89.
+
+ * NOTE 2: headers lie.  Do not expect that if HAS_C99 gets to be true,
+ * all the C99 features are there and are correct. */
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+     defined(_STDC_C99)
 #  define HAS_C99 1
 #endif
 
@@ -1945,7 +1952,9 @@ EXTERN_C long double modfl(long double, long double *);
 #           define Perl_isinf(x) ((x) > LDBL_MAX || (x) < -LDBL_MAX)
 #       endif
 #   endif
-#   define Perl_isfinite(x) Perl_isfinitel(x)
+#   ifndef Perl_isfinite
+#       define Perl_isfinite(x) Perl_isfinitel(x)
+#   endif
 #else
 #   define NV_DIG DBL_DIG
 #   ifdef DBL_MANT_DIG
@@ -2023,11 +2032,6 @@ EXTERN_C long double modfl(long double, long double *);
 #       define Perl_isfinite(x) isfinite(x)
 #     elif defined(HAS_FINITE)
 #       define Perl_isfinite(x) finite(x)
-#     else
-/* For the infinities the multiplication returns nan,
- * for the nan the multiplication also returns nan,
- * for everything else (that is, finite) zero should be returned. */
-#       define Perl_isfinite(x) ((x) * 0 == 0)
 #     endif
 #   endif
 #endif
@@ -2284,13 +2288,15 @@ int isnan(double d);
 
 #ifndef Perl_isfinite
 #   if defined(HAS_ISFINITE) && !defined(isfinite)
-#     define Perl_isfinite(x) isfinite((double)x)
+#     define Perl_isfinite(x) isfinite((double)(x))
 #   elif defined(HAS_FINITE)
-#       define Perl_isfinite(x) finite((double)x)
+#       define Perl_isfinite(x) finite((double)(x))
 #   elif defined(Perl_fp_class_finite)
 #     define Perl_isfinite(x) Perl_fp_class_finite(x)
 #   else
-/* NaN*0 is NaN, [+-]Inf*0 is NaN, zero for anything else. */
+/* For the infinities the multiplication returns nan,
+ * for the nan the multiplication also returns nan,
+ * for everything else (that is, finite) zero should be returned. */
 #     define Perl_isfinite(x) (((x) * 0) == 0)
 #   endif
 #endif
@@ -2307,7 +2313,7 @@ int isnan(double d);
 #if defined(HAS_LONG_DOUBLE) && !defined(Perl_isfinitel)
 /* If isfinite() is a macro and looks like we have C99,
  * we assume it's the type-aware C99 isfinite(). */
-#    if defined(isfinite) && defined(HAS_C99)
+#    if defined(HAS_ISFINITE) && defined(isfinite) && defined(HAS_C99)
 #        define Perl_isfinitel(x) isfinite(x)
 #    elif defined(HAS_ISFINITEL)
 #        define Perl_isfinitel(x) isfinitel(x)
@@ -4136,9 +4142,8 @@ END_EXTERN_C
 #  if !defined(NV_INF) && defined(HUGE_VAL)
 #    define NV_INF HUGE_VAL
 #  endif
-#  ifndef NV_NAN
-#    define NV_NAN (NV_INF-NV_INF)
-#  endif
+/* For WIN32 the best NV_NAN is the __PL_nan_u trick, see below.
+ * There is no supported way of getting the NAN across all the crts. */
 #endif
 
 /* If you are thinking of using HUGE_VAL for infinity, or using
@@ -4235,6 +4240,9 @@ static const union { unsigned int __i; float __f; } __PL_nan_u =
 #if !defined(NV_NAN)
 #  define NV_NAN ((NV)0.0/0.0) /* Some compilers will warn. */
 #endif
+/* Do NOT try doing NV_NAN based on NV_INF and trying (NV_INF-NV_INF).
+ * Though IEEE-754-logically correct, some compilers (like Visual C 2003)
+ * falsely misoptimize that to zero (x-x is zero, right?) */
 
 #ifndef __cplusplus
 #  if !defined(WIN32) && !defined(VMS)