This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
NV_INF/NV_NAN fallback where int32 is coerced to IEEE754 float.
[perl5.git] / perl.h
diff --git a/perl.h b/perl.h
index 8ea9a2a..865daa8 100644 (file)
--- a/perl.h
+++ b/perl.h
 
 /* gcc -Wall:
  * for silencing unused variables that are actually used most of the time,
- * but we cannot quite get rid of, such as "ax" in PPCODE+noargs xsubs
+ * but we cannot quite get rid of, such as "ax" in PPCODE+noargs xsubs,
+ * or variables/arguments that are used only in certain configurations.
  */
 #ifndef PERL_UNUSED_ARG
 #  if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */
 #    include <note.h>
 #    define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x))
 #  else
-#    define PERL_UNUSED_ARG(x) ((void)x)
+#    define PERL_UNUSED_ARG(x) ((void)sizeof(x))
 #  endif
 #endif
 #ifndef PERL_UNUSED_VAR
-#  define PERL_UNUSED_VAR(x) ((void)x)
+#  define PERL_UNUSED_VAR(x) ((void)sizeof(x))
 #endif
 
 #if defined(USE_ITHREADS) || defined(PERL_GLOBAL_STRUCT)
@@ -1894,6 +1895,14 @@ typedef NVTYPE NV;
 #       define Perl_floor floorl
 #       define Perl_ceil ceill
 #       define Perl_fmod fmodl
+#       define Perl_acos acosl
+#       define Perl_asin asinl
+#       define Perl_atan atanl
+#       define Perl_cosh coshl
+#       define Perl_log10 log10l
+#       define Perl_sinh sinhl
+#       define Perl_tan tanl
+#       define Perl_tanh tanhl
 #   endif
 /* e.g. libsunmath doesn't have modfl and frexpl as of mid-March 2000 */
 #   ifdef HAS_MODFL
@@ -1932,6 +1941,8 @@ EXTERN_C long double modfl(long double, long double *);
 #   ifndef Perl_isinf
 #       if defined(HAS_ISINFL) && !(defined(isinf) && HAS_C99)
 #           define Perl_isinf(x) isinfl(x)
+#       elif defined(LDBL_MAX)
+#           define Perl_isinf(x) ((x) > LDBL_MAX || (x) < -LDBL_MAX)
 #       endif
 #   endif
 #   if !defined(Perl_isfinite) && !(defined(isfinite) && HAS_C99)
@@ -1939,6 +1950,8 @@ EXTERN_C long double modfl(long double, long double *);
 #       define Perl_isfinite(x) isfinitel(x)
 #     elif defined(HAS_FINITEL)
 #       define Perl_isfinite(x) finitel(x)
+#     elif defined(LDBL_MAX)
+#       define Perl_isfinite(x) ((x) <= LDBL_MAX && (x) >= -LDBL_MAX)
 #     endif
 #   endif
 #else
@@ -1988,6 +2001,14 @@ EXTERN_C long double modfl(long double, long double *);
 #   define Perl_modf(x,y) modf(x,y)
 #   define Perl_frexp(x,y) frexp(x,y)
 #   define Perl_ldexp(x,y) ldexp(x,y)
+#   define Perl_acos acos
+#   define Perl_asin asin
+#   define Perl_atan atan
+#   define Perl_cosh cosh
+#   define Perl_log10 log10
+#   define Perl_sinh sinh
+#   define Perl_tan tan
+#   define Perl_tanh tanh
 #   ifndef Perl_isnan
 #       ifdef HAS_ISNAN
 #           define Perl_isnan(x) isnan(x)
@@ -1996,6 +2017,8 @@ EXTERN_C long double modfl(long double, long double *);
 #   ifndef Perl_isinf
 #       if defined(HAS_ISINF)
 #           define Perl_isinf(x) isinf(x)
+#       elif defined(DBL_MAX)
+#           define Perl_isinf(x) ((x) > DBL_MAX || (x) < -DBL_MAX)
 #       endif
 #   endif
 #   ifndef Perl_isfinite
@@ -2003,6 +2026,8 @@ 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)
+#     elif defined(DBL_MAX)
+#       define Perl_isfinite(x) ((x) <= DBL_MAX && (x) >= -DBL_MAX)
 #     endif
 #   endif
 #endif
@@ -2024,7 +2049,7 @@ EXTERN_C long double modfl(long double, long double *);
 #        define Perl_fp_class(x)       fpclassify(x)
 #        define Perl_fp_class_pinf(x)  (Perl_fp_class(x)==FP_PLUS_INF)
 #        define Perl_fp_class_ninf(x)  (Perl_fp_class(x)==FP_MINUS_INF)
-#        define Perl_fp_class_snan(x)  (Perl_fp_class(x)==FP_QNAN)
+#        define Perl_fp_class_snan(x)  (Perl_fp_class(x)==FP_SNAN)
 #        define Perl_fp_class_qnan(x)  (Perl_fp_class(x)==FP_QNAN)
 #        define Perl_fp_class_pnorm(x) (Perl_fp_class(x)==FP_PLUS_NORM)
 #        define Perl_fp_class_nnorm(x) (Perl_fp_class(x)==FP_MINUS_NORM)
@@ -2044,6 +2069,9 @@ EXTERN_C long double modfl(long double, long double *);
 #    ifdef __VMS
      /* FP_INFINITE and others are here rather than in math.h as C99 stipulates */
 #        include <fp.h>
+     /* oh, and the isnormal macro has a typo in it! */
+#    undef isnormal
+#    define isnormal(x) Perl_fp_class_norm(x)
 #    endif
 #    if defined(FP_INFINITE) && defined(FP_NAN)
 #        define Perl_fp_class(x)       fp_classify(x)
@@ -2186,7 +2214,7 @@ EXTERN_C long double modfl(long double, long double *);
  * returns a set of bits. */
 #    define Perl_fp_class_snan(x) (_fpclass(x) & _FPCLASS_SNAN)
 #    define Perl_fp_class_qnan(x) (_fpclass(x) & _FPCLASS_QNAN)
-#    define Perl_fp_class_nan(x) (_fpclass(x) & (_FPCLASS_QNAN|_FPCLASS_QNAN))
+#    define Perl_fp_class_nan(x) (_fpclass(x) & (_FPCLASS_SNAN|_FPCLASS_QNAN))
 #    define Perl_fp_class_ninf(x) (_fpclass(x) & _FPCLASS_NINF))
 #    define Perl_fp_class_pinf(x) (_fpclass(x) & _FPCLASS_PINF))
 #    define Perl_fp_class_inf(x) (_fpclass(x) & (_FPCLASS_NINF|_FPCLASS_PINF))
@@ -4094,6 +4122,12 @@ END_EXTERN_C
 #  endif
 #endif
 
+/* If you are thinking of using HUGE_VAL for infinity, or using
+ * <math.h> functions to generate NV_INF (e.g. exp(1e9), log(-1.0)),
+ * stop.  Neither will work portably: HUGE_VAL can be just DBL_MAX,
+ * and the math functions might be just generating DBL_MAX, or even
+ * zero.  */
+
 #if !defined(NV_INF) && defined(USE_LONG_DOUBLE) && defined(LDBL_INFINITY)
 #  define NV_INF LDBL_INFINITY
 #endif
@@ -4106,11 +4140,31 @@ END_EXTERN_C
 #if !defined(NV_INF) && defined(INF)
 #  define NV_INF (NV)INF
 #endif
-#if !defined(NV_INF) && defined(USE_LONG_DOUBLE) && defined(HUGE_VALL)
-#  define NV_INF (NV)HUGE_VALL
+#if !defined(NV_INF)
+#  if INTSIZE == 4
+/* At this point we assume the IEEE 754 floating point (and of course,
+ * we also assume a floating point format that can encode an infinity).
+ * We will coerce an int32 (which will encode the infinity) into
+ * a 32-bit float, which will then be cast into NV.
+ *
+ * Note that we intentionally use a float and 32-bit int, instead of
+ * shifting a small integer into a full IV, and from that into a full
+ * NV, because:
+ *
+ * (1) an IV might not be wide enough to cover all the bits of an NV.
+ * (2) the exponent part (including the infinity and nan bits) of a NV
+ *     might be wider than just 16 bits.
+ *
+ * Below the NV_NAN logic has similar __PL_nan_u fallback, the only
+ * difference being the int32 constant being coerced. */
+#    define __PL_inf_float_int32 0x7F800000
+static const union { unsigned int __i; float __f; } __PL_inf_u =
+    { __PL_inf_float_int32 };
+#    define NV_INF ((NV)(__PL_inf_u.__f))
+#  endif
 #endif
-#if !defined(NV_INF) && defined(HUGE_VAL)
-#  define NV_INF (NV)HUGE_VAL
+#if !defined(NV_INF)
+#  define NV_INF ((NV)1.0/0.0) /* Some compilers will warn. */
 #endif
 
 #if !defined(NV_NAN) && defined(USE_LONG_DOUBLE)
@@ -4136,14 +4190,23 @@ END_EXTERN_C
 #if !defined(NV_NAN) && defined(QNAN)
 #  define NV_NAN (NV)QNAN
 #endif
+#if !defined(NV_NAN) && defined(NAN)
+#  define NV_NAN (NV)NAN
+#endif
 #if !defined(NV_NAN) && defined(SNAN)
 #  define NV_NAN (NV)SNAN
 #endif
-#if !defined(NV_NAN) && defined(NAN)
-#  define NV_NAN (NV)NAN
+#if !defined(NV_NAN)
+#  if INTSIZE == 4
+/* See the discussion near __PL_inf_u. */
+#    define __PL_nan_float_int32 0x7FC00000
+static const union { unsigned int __i; float __f; } __PL_nan_u =
+    { __PL_nan_float_int32 };
+#    define NV_NAN ((NV)(__PL_nan_u.__f))
+#  endif
 #endif
-#if !defined(NV_NAN) && defined(NV_INF)
-#  define NV_NAN (NV_INF-NV_INF)
+#if !defined(NV_NAN)
+#  define NV_NAN ((NV)0.0/0.0) /* Some compilers will warn. */
 #endif
 
 #ifndef __cplusplus