summaryrefslogtreecommitdiff
path: root/perl.h
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2014-08-31 08:34:10 -0400
committerJarkko Hietaniemi <jhi@iki.fi>2014-08-31 12:14:23 -0400
commit25c46df8dc6aa595a691c33917e6457c632a40aa (patch)
tree35c0d4b6516a8de03027eebc826b1d0ce53b6490 /perl.h
parent10decdeb9bd4a71279d64552b9a4d9b038bda788 (diff)
downloadperl-25c46df8dc6aa595a691c33917e6457c632a40aa.tar.gz
The fp classification is a royal mess.
Try avoiding false detections by guarding against an interface falsely matching a set of return values. This can still go wrong if <math.h> declares several sets. Would really need an array of Configure tests.
Diffstat (limited to 'perl.h')
-rw-r--r--perl.h163
1 files changed, 102 insertions, 61 deletions
diff --git a/perl.h b/perl.h
index 354286cad7..5c296dc34b 100644
--- a/perl.h
+++ b/perl.h
@@ -2011,19 +2011,46 @@ 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_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_MINUIS_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>
+# 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 +2060,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 +2079,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 +2090,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 +2101,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 +2112,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,6 +2178,8 @@ 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))
@@ -2208,26 +2247,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.