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 354286c..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
@@ -2011,19 +2036,53 @@ EXTERN_C long double modfl(long double, long double *);
 * the sizeof() of its argument, so there's no need for e.g. fpclassifyl().*/
 #if !defined(Perl_fp_class) && defined(HAS_FPCLASSIFY)
 #    include <math.h>
-#    define Perl_fp_class(x)           fpclassify(x)
-#    define Perl_fp_class_inf(x)       (Perl_fp_class(x)==FP_INFINITE)
-#    define Perl_fp_class_nan(x)       (Perl_fp_class(x)==FP_NAN)
-#    define Perl_fp_class_norm(x)      (Perl_fp_class(x)==FP_NORMAL)
-#    define Perl_fp_class_denorm(x)    (Perl_fp_class(x)==FP_SUBNORMAL)
-#    define Perl_fp_class_zero(x)      (Perl_fp_class(x)==FP_ZERO)
+#    if defined(FP_INFINITE) && defined(FP_NAN)
+#        define Perl_fp_class(x)       fpclassify(x)
+#        define Perl_fp_class_inf(x)   (Perl_fp_class(x)==FP_INFINITE)
+#        define Perl_fp_class_nan(x)   (Perl_fp_class(x)==FP_NAN)
+#        define Perl_fp_class_norm(x)  (Perl_fp_class(x)==FP_NORMAL)
+#        define Perl_fp_class_denorm(x)        (Perl_fp_class(x)==FP_SUBNORMAL)
+#        define Perl_fp_class_zero(x)  (Perl_fp_class(x)==FP_ZERO)
+#    elif defined(FP_PLUS_INF) && defined(FP_QNAN)
+/* Some versions of HP-UX (10.20) have (only) fpclassify() but which is
+ * actually not the C99 fpclassify, with its own set of return defines. */
+#        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_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)
+#        define Perl_fp_class_pdenorm(x)       (Perl_fp_class(x)==FP_PLUS_DENORM)
+#        define Perl_fp_class_ndenorm(x)       (Perl_fp_class(x)==FP_MINUS_DENORM)
+#        define Perl_fp_class_pzero(x) (Perl_fp_class(x)==FP_PLUS_ZERO)
+#        define Perl_fp_class_nzero(x) (Perl_fp_class(x)==FP_MINUS_ZERO)
+#    else
+#        undef Perl_fp_class /* Unknown set of defines */
+#    endif
 #endif
 
-/* Solaris and IRIX have fpclass/fpclassl, but they are using
- * an enum typedef, not cpp symbols, and Configure doesn't detect that.
- * Define one symbol also as a cpp symbol so we can detect it. */
-#if defined(__sun) || defined(__irix__) /* XXX Configure test instead */
-# define FP_SNAN FP_SNAN
+/* fp_classify(): Legacy: VMS, maybe Unicos? The values, however,
+ * are identical to the C99 fpclassify(). */
+#if !defined(Perl_fp_class) && defined(HAS_FP_CLASSIFY)
+#    include <math.h>
+#    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)
+#        define Perl_fp_class_inf(x)   (Perl_fp_class(x)==FP_INFINITE)
+#        define Perl_fp_class_nan(x)   (Perl_fp_class(x)==FP_NAN)
+#        define Perl_fp_class_norm(x)  (Perl_fp_class(x)==FP_NORMAL)
+#        define Perl_fp_class_denorm(x)        (Perl_fp_class(x)==FP_SUBNORMAL)
+#        define Perl_fp_class_zero(x)  (Perl_fp_class(x)==FP_ZERO)
+#    else
+#        undef Perl_fp_class /* Unknown set of defines */
+#    endif
 #endif
 
 /* Feel free to check with me for the SGI manpages, SGI testing,
@@ -2033,6 +2092,13 @@ EXTERN_C long double modfl(long double, long double *);
 
 /* fpclass(): SysV, at least Solaris and some versions of IRIX. */
 #if !defined(Perl_fp_class) && (defined(HAS_FPCLASS)||defined(HAS_FPCLASSL))
+/* Solaris and IRIX have fpclass/fpclassl, but they are using
+ * an enum typedef, not cpp symbols, and Configure doesn't detect that.
+ * Define some symbols also as cpp symbols so we can detect them. */
+#    if defined(__sun) || defined(__irix__) /* XXX Configure test instead */
+#     define FP_PINF FP_PINF
+#     define FP_QNAN FP_QNAN
+#    endif
 #    include <math.h>
 #    ifdef I_IEEFP
 #        include <ieeefp.h>
@@ -2045,7 +2111,7 @@ EXTERN_C long double modfl(long double, long double *);
 #    else
 #        define Perl_fp_class(x)       fpclass(x)
 #    endif
-#    ifdef FP_CLASS_SNAN
+#    if defined(FP_CLASS_PINF) && defined(FP_CLASS_SNAN)
 #        define Perl_fp_class_snan(x)  (Perl_fp_class(x)==FP_CLASS_SNAN)
 #        define Perl_fp_class_qnan(x)  (Perl_fp_class(x)==FP_CLASS_QNAN)
 #        define Perl_fp_class_ninf(x)  (Perl_fp_class(x)==FP_CLASS_NINF)
@@ -2056,7 +2122,7 @@ EXTERN_C long double modfl(long double, long double *);
 #        define Perl_fp_class_pdenorm(x)       (Perl_fp_class(x)==FP_CLASS_PDENORM)
 #        define Perl_fp_class_nzero(x) (Perl_fp_class(x)==FP_CLASS_NZERO)
 #        define Perl_fp_class_pzero(x) (Perl_fp_class(x)==FP_CLASS_PZERO)
-#    elif defined(FP_SNAN)
+#    elif defined(FP_PINF) && defined(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_ninf(x)  (Perl_fp_class(x)==FP_NINF)
@@ -2067,6 +2133,8 @@ EXTERN_C long double modfl(long double, long double *);
 #        define Perl_fp_class_pdenorm(x)       (Perl_fp_class(x)==FP_PDENORM)
 #        define Perl_fp_class_nzero(x) (Perl_fp_class(x)==FP_NZERO)
 #        define Perl_fp_class_pzero(x) (Perl_fp_class(x)==FP_PZERO)
+#    else
+#        undef Perl_fp_class /* Unknown set of defines */
 #    endif
 #endif
 
@@ -2076,60 +2144,61 @@ EXTERN_C long double modfl(long double, long double *);
 #    if !defined(FP_SNAN) && defined(I_FP_CLASS)
 #        include <fp_class.h>
 #    endif
-#    ifdef __irix__ /* XXX Configure test instead */
-#        ifdef USE_LONG_DOUBLE
-#            define Perl_fp_class(x)   fp_class_l(x)
+#    if defined(FP_POS_INF) && defined(FP_QNAN)
+#        ifdef __irix__ /* XXX Configure test instead */
+#            ifdef USE_LONG_DOUBLE
+#                define Perl_fp_class(x)       fp_class_l(x)
+#            else
+#                define Perl_fp_class(x)       fp_class_d(x)
+#            endif
 #        else
-#            define Perl_fp_class(x)   fp_class_d(x)
+#            if defined(USE_LONG_DOUBLE) && defined(HAS_FP_CLASSL)
+#                define Perl_fp_class(x)       fp_classl(x)
+#            else
+#                define Perl_fp_class(x)       fp_class(x)
+#            endif
 #        endif
-#    else
-#        if defined(USE_LONG_DOUBLE) && defined(HAS_FP_CLASSL)
-#            define Perl_fp_class(x)   fp_classl(x)
+#        if defined(FP_POS_INF) && defined(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_ninf(x)      (Perl_fp_class(x)==FP_NEG_INF)
+#            define Perl_fp_class_pinf(x)      (Perl_fp_class(x)==FP_POS_INF)
+#            define Perl_fp_class_nnorm(x)     (Perl_fp_class(x)==FP_NEG_NORM)
+#            define Perl_fp_class_pnorm(x)     (Perl_fp_class(x)==FP_POS_NORM)
+#            define Perl_fp_class_ndenorm(x)   (Perl_fp_class(x)==FP_NEG_DENORM)
+#            define Perl_fp_class_pdenorm(x)   (Perl_fp_class(x)==FP_POS_DENORM)
+#            define Perl_fp_class_nzero(x)     (Perl_fp_class(x)==FP_NEG_ZERO)
+#            define Perl_fp_class_pzero(x)     (Perl_fp_class(x)==FP_POS_ZERO)
 #        else
-#            define Perl_fp_class(x)   fp_class(x)
+#            undef Perl_fp_class /* Unknown set of defines */
 #        endif
 #    endif
-#    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_ninf(x)      (Perl_fp_class(x)==FP_NEG_INF)
-#    define Perl_fp_class_pinf(x)      (Perl_fp_class(x)==FP_POS_INF)
-#    define Perl_fp_class_nnorm(x)     (Perl_fp_class(x)==FP_NEG_NORM)
-#    define Perl_fp_class_pnorm(x)     (Perl_fp_class(x)==FP_POS_NORM)
-#    define Perl_fp_class_ndenorm(x)   (Perl_fp_class(x)==FP_NEG_DENORM)
-#    define Perl_fp_class_pdenorm(x)   (Perl_fp_class(x)==FP_POS_DENORM)
-#    define Perl_fp_class_nzero(x)     (Perl_fp_class(x)==FP_NEG_ZERO)
-#    define Perl_fp_class_pzero(x)     (Perl_fp_class(x)==FP_POS_ZERO)
 #endif
 
 /* class(), _class(): Legacy: AIX. */
 #if !defined(Perl_fp_class) && defined(HAS_CLASS)
 #    include <math.h>
-#    ifndef _cplusplus
-#        define Perl_fp_class(x)       class(x)
-#    else
-#        define Perl_fp_class(x)       _class(x)
+#    if defined(FP_PLUS_NORM) && defined(FP_PLUS_INF)
+#        ifndef _cplusplus
+#            define Perl_fp_class(x)   class(x)
+#        else
+#            define Perl_fp_class(x)   _class(x)
+#        endif
+#        if defined(FP_PLUS_INF) && defined(FP_NANQ)
+#            define Perl_fp_class_snan(x)      (Perl_fp_class(x)==FP_NANS)
+#            define Perl_fp_class_qnan(x)      (Perl_fp_class(x)==FP_NANQ)
+#            define Perl_fp_class_ninf(x)      (Perl_fp_class(x)==FP_MINUS_INF)
+#            define Perl_fp_class_pinf(x)      (Perl_fp_class(x)==FP_PLUS_INF)
+#            define Perl_fp_class_nnorm(x)     (Perl_fp_class(x)==FP_MINUS_NORM)
+#            define Perl_fp_class_pnorm(x)     (Perl_fp_class(x)==FP_PLUS_NORM)
+#            define Perl_fp_class_ndenorm(x)   (Perl_fp_class(x)==FP_MINUS_DENORM)
+#            define Perl_fp_class_pdenorm(x)   (Perl_fp_class(x)==FP_PLUS_DENORM)
+#            define Perl_fp_class_nzero(x)     (Perl_fp_class(x)==FP_MINUS_ZERO)
+#            define Perl_fp_class_pzero(x)     (Perl_fp_class(x)==FP_PLUS_ZERO)
+#        else
+#            undef Perl_fp_class /* Unknown set of defines */
+#        endif
 #    endif
-#    define Perl_fp_class_snan(x)      (Perl_fp_class(x)==FP_NANS)
-#    define Perl_fp_class_qnan(x)      (Perl_fp_class(x)==FP_NANQ)
-#    define Perl_fp_class_ninf(x)      (Perl_fp_class(x)==FP_MINUS_INF)
-#    define Perl_fp_class_pinf(x)      (Perl_fp_class(x)==FP_PLUS_INF)
-#    define Perl_fp_class_nnorm(x)     (Perl_fp_class(x)==FP_MINUS_NORM)
-#    define Perl_fp_class_pnorm(x)     (Perl_fp_class(x)==FP_PLUS_NORM)
-#    define Perl_fp_class_ndenorm(x)   (Perl_fp_class(x)==FP_MINUS_DENORM)
-#    define Perl_fp_class_pdenorm(x)   (Perl_fp_class(x)==FP_PLUS_DENORM)
-#    define Perl_fp_class_nzero(x)     (Perl_fp_class(x)==FP_MINUS_ZERO)
-#    define Perl_fp_class_pzero(x)     (Perl_fp_class(x)==FP_PLUS_ZERO)
-#endif
-
-/* fp_classify(): Legacy: VMS, maybe Unicos? */
-#if !defined(Perl_fp_class) && defined(HAS_FP_CLASSIFY)
-#    include <math.h>
-#    define Perl_fp_class(x)           fp_classify(x)
-#    define Perl_fp_class_inf(x)       (Perl_fp_class(x)==FP_INFINITE)
-#    define Perl_fp_class_nan(x)       (Perl_fp_class(x)==FP_NAN)
-#    define Perl_fp_class_norm(x)      (Perl_fp_class(x)==FP_NORMAL)
-#    define Perl_fp_class_denorm(x)    (Perl_fp_class(x)==FP_SUBNORMAL)
-#    define Perl_fp_class_zero(x)      (Perl_fp_class(x)==FP_ZERO)
 #endif
 
 /* Win32: _fpclass(), _isnan(), _finite(). */
@@ -2141,9 +2210,11 @@ EXTERN_C long double modfl(long double, long double *);
 #    define Perl_isfinite(x) _finite(x)
 #  endif
 #  ifndef Perl_fp_class_snan
+/* No simple way to #define Perl_fp_class because _fpclass()
+ * 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))
@@ -2208,26 +2279,28 @@ int isnan(double d);
 #ifndef Perl_isinf
 #   ifdef Perl_fp_class_inf
 #       define Perl_isinf(x) Perl_fp_class_inf(x)
-#   elif defined(Perl_isfinite) && defined(Perl_isnan)
-#       define Perl_isinf(x) !(Perl_isfinite(x)||Perl_isnan(x))
 #   endif
 #endif
 
 #ifndef Perl_isfinite
-#   ifdef HAS_ISFINITE
+#   if defined(HAS_ISFINITE) && !defined(isfinite)
 #     define Perl_isfinite(x) isfinite((double)x)
 #   elif defined(HAS_FINITE)
 #       define Perl_isfinite(x) finite((double)x)
 #   elif defined(Perl_fp_class_finite)
 #     define Perl_isfinite(x) Perl_fp_class_finite(x)
-#   elif defined(Perl_is_inf) && defined(Perl_is_nan)
-#     define Perl_isfinite(x) !(Perl_is_inf(x)||Perl_is_nan(x))
 #   else
 /* NaN*0 is NaN, [+-]Inf*0 is NaN, zero for anything else. */
 #     define Perl_isfinite(x) (((x) * 0) == 0)
 #   endif
 #endif
 
+#ifndef Perl_isinf
+#   if defined(Perl_isfinite) && defined(Perl_isnan)
+#       define Perl_isinf(x) !(Perl_isfinite(x)||Perl_isnan(x))
+#   endif
+#endif
+
 /* The default is to use Perl's own atof() implementation (in numeric.c).
  * Usually that is the one to use but for some platforms (e.g. UNICOS)
  * it is however best to use the native implementation of atof.
@@ -4049,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
@@ -4061,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)
@@ -4091,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