# include "config.h"
#endif
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(_STDC_C99)
+# define HAS_C99 1
+#endif
+
/* See L<perlguts/"The Perl API"> for detailed notes on
* PERL_IMPLICIT_CONTEXT and PERL_IMPLICIT_SYS */
# endif
#endif
+#ifdef I_STDINT
+# include <stdint.h>
+#endif
+
#include <ctype.h>
#ifdef METHOD /* Defined by OSF/1 v3.0 by ctype.h */
# endif
# endif
# ifndef Perl_isnan
-# ifdef HAS_ISNANL
+# if defined(HAS_ISNANL) && !(defined(isnan) && HAS_C99)
# define Perl_isnan(x) isnanl(x)
# endif
# endif
# ifndef Perl_isinf
-# if defined(HAS_ISINFL)
+# 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
-# ifndef Perl_isfinite
+# if !defined(Perl_isfinite) && !(defined(isfinite) && HAS_C99)
# ifdef HAS_ISFINITEL
# 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
# define Perl_modf(x,y) modf(x,y)
# define Perl_frexp(x,y) frexp(x,y)
# define Perl_ldexp(x,y) ldexp(x,y)
+# ifndef Perl_isnan
+# ifdef HAS_ISNAN
+# define Perl_isnan(x) isnan(x)
+# endif
+# endif
+# 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
+# ifdef HAS_ISFINITE
+# 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
-/* 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
+/* fpclassify(): C99. It is supposed to be a macro that switches on
+* 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>
+# 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_QNAN)
+# 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
+
+/* 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,
+ * etcetera, if you want to try getting this to work with IRIX.
+ *
+ * - Allen <allens@cpan.org> */
+
+/* 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>
# 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)
# 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)
# 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
-/* Feel free to check with me for the SGI manpages, SGI testing,
- * etcetera, if you want to try getting this to work with IRIX.
- *
- * - Allen <allens@cpan.org> */
-
-#if !defined(Perl_fp_class) && defined(HAS_FP_CLASS)
+/* fp_class(): Legacy: at least Tru64, some versions of IRIX. */
+#if !defined(Perl_fp_class) && (defined(HAS_FP_CLASS)||defined(HAS_FP_CLASSL))
# include <math.h>
# 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
+# 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
+# undef Perl_fp_class /* Unknown set of defines */
# endif
-# else
-# define Perl_fp_class(x) fp_class(x)
# endif
-# define Perl_fp_class_snan(x) (fp_class(x)==FP_SNAN)
-# define Perl_fp_class_qnan(x) (fp_class(x)==FP_QNAN)
-# define Perl_fp_class_ninf(x) (fp_class(x)==FP_NEG_INF)
-# define Perl_fp_class_pinf(x) (fp_class(x)==FP_POS_INF)
-# define Perl_fp_class_nnorm(x) (fp_class(x)==FP_NEG_NORM)
-# define Perl_fp_class_pnorm(x) (fp_class(x)==FP_POS_NORM)
-# define Perl_fp_class_ndenorm(x) (fp_class(x)==FP_NEG_DENORM)
-# define Perl_fp_class_pdenorm(x) (fp_class(x)==FP_POS_DENORM)
-# define Perl_fp_class_nzero(x) (fp_class(x)==FP_NEG_ZERO)
-# define Perl_fp_class_pzero(x) (fp_class(x)==FP_POS_ZERO)
-#endif
-
-#if !defined(Perl_fp_class) && defined(HAS_FPCLASSIFY)
-# include <math.h>
-# define Perl_fp_class(x) fpclassify(x)
-# define Perl_fp_class_inf(x) (fp_classify(x)==FP_INFINITE)
-# define Perl_fp_class_snan(x) (fp_classify(x)==FP_SNAN)
-# define Perl_fp_class_qnan(x) (fp_classify(x)==FP_QNAN)
-# define Perl_fp_class_norm(x) (fp_classify(x)==FP_NORMAL)
-# define Perl_fp_class_denorm(x) (fp_classify(x)==FP_SUBNORMAL)
-# define Perl_fp_class_zero(x) (fp_classify(x)==FP_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
+/* Win32: _fpclass(), _isnan(), _finite(). */
#ifdef WIN32
# ifndef Perl_isnan
# define Perl_isnan(x) _isnan(x)
# 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))
(Perl_fp_class_pdenorm(x) || Perl_fp_class_ndenorm(x))
#endif
+#ifdef UNDER_CE
+int isnan(double d);
+#endif
+
#ifndef Perl_isnan
-# ifdef HAS_ISNAN
-# define Perl_isnan(x) isnan((double)x)
+# ifdef Perl_fp_class_nan
+# define Perl_isnan(x) Perl_fp_class_nan(x)
# else
-# ifdef Perl_fp_class_nan
-# define Perl_isnan(x) Perl_fp_class_nan(x)
+# ifdef HAS_UNORDERED
+# define Perl_isnan(x) unordered((x), 0.0)
# else
-# ifdef HAS_UNORDERED
-# define Perl_isnan(x) unordered((x), 0.0)
-# else
-# define Perl_isnan(x) ((x)!=(x))
-# endif
+# define Perl_isnan(x) ((x)!=(x))
# endif
# endif
#endif
-#ifdef UNDER_CE
-int isnan(double d);
+#ifndef Perl_isinf
+# ifdef Perl_fp_class_inf
+# define Perl_isinf(x) Perl_fp_class_inf(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
#ifndef Perl_isinf
-# if defined(Perl_fp_class_inf)
-# define Perl_isinf(x) Perl_fp_class_inf(x)
-# elif defined(Perl_isfinite) && defined(Perl_isnan)
+# if defined(Perl_isfinite) && defined(Perl_isnan)
# define Perl_isinf(x) !(Perl_isfinite(x)||Perl_isnan(x))
# endif
#endif
#ifdef I_MATH
# include <math.h>
+# ifdef __VMS
+ /* isfinite and others are here rather than in math.h as C99 stipulates */
+# include <fp.h>
+# endif
#else
START_EXTERN_C
double exp (double);
# 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
#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
-#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)
#if !defined(NV_NAN) && defined(QNAN)
# define NV_NAN (NV)QNAN
#endif
-#if !defined(NV_NAN) && defined(SNAN)
-# define NV_NAN (NV)SNAN
-#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(NV_INF)
-# define NV_NAN (NV_INF-NV_INF)
+# define NV_NAN ((NV)0.0/0.0) /* Some compilers will warn. */
#endif
#ifndef __cplusplus