summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-02-29 17:31:52 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-02-29 17:31:52 +0000
commit694fe0b0aa8c7624f4fa2972a803a2a2ca45e002 (patch)
tree81a65de97919b91f1760ac97e2a5fbb42466e9b2
parentf195d7e1d80c77d394ff34bfdfdada65f3deea4c (diff)
downloadmpfr-694fe0b0aa8c7624f4fa2972a803a2a2ca45e002.tar.gz
native detection of ieee_double_extract (work in progress),
this will allow to have decimal-float support without gmp-build (and also faster set_d/get_d) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@10144 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--configure.ac51
-rw-r--r--src/mpfr-gmp.h63
2 files changed, 103 insertions, 11 deletions
diff --git a/configure.ac b/configure.ac
index 7b944d92a..10368870f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,6 +252,40 @@ AC_LANG(C)
dnl Support unusual archivers.
AM_PROG_AR
+dnl Try to determine the double format
+AC_MSG_CHECKING(format of `double')
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <stdint.h>
+]], [[
+union ieee_double_extract
+{
+ double d;
+ uint32_t x[2];
+} t;
+t.d = 1.000000476837158203125; /* 1 + 1/2^21, which has manl = 2^31,
+ manh = 0, exp = 1023 and sig = 0 */
+if (t.x[0] == 2147483648UL && t.x[1] == 1072693248UL)
+ return 1; /* little endian */
+else if (t.x[0] == 1072693248UL && t.x[1] == 2147483648UL)
+ return 2; /* little endian swapped */
+else if (t.x[0] == 1024 && t.x[1] == 2147483648UL)
+ return 3; /* big endian */
+else
+ return 0; /* unknown */
+]])],
+ [mpfr_ieee_double=$?],
+ [mpfr_ieee_double=$?],
+ [mpfr_ieee_double=0])
+case "$mpfr_ieee_double" in
+ 1) AC_MSG_RESULT(little endian)
+ AC_DEFINE(HAVE_DOUBLE_IEEE_LITTLE_ENDIAN) ;;
+ 2) AC_MSG_RESULT(little endian swapped)
+ AC_DEFINE(HAVE_DOUBLE_IEEE_LITTLE_SWAPPED) ;;
+ 3) AC_MSG_RESULT(big endian)
+ AC_DEFINE(HAVE_DOUBLE_IEEE_BIG_ENDIAN) ;;
+ *) AC_MSG_ERROR(format of 'double' not recognized) ;;
+esac
+
dnl For GCC, _Decimal64 was introduced in GCC 4.3 for some targets
dnl (note that it is not guaranteed to be available because it may
dnl be disabled in the GCC build). See:
@@ -270,17 +304,12 @@ AC_ARG_ENABLE(decimal-float,
AC_MSG_CHECKING(if compiler knows _Decimal64)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[_Decimal64 x;]])],
[AC_MSG_RESULT(yes)
- if test "$use_gmp_build" != yes ; then
- AC_MSG_ERROR([decimal float support requires --with-gmp-build])
- fi
- AC_MSG_CHECKING(if _GMP_IEEE_FLOATS is defined)
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
-#include "gmp.h"
-#include "gmp-impl.h"
-#ifndef _GMP_IEEE_FLOATS
-#error "_GMP_IEEE_FLOATS is not defined"
-#endif]])],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
- AC_MSG_ERROR([decimal float support requires _GMP_IEEE_FLOATS])])
+ AC_MSG_CHECKING(if 'double' format is known)
+ case $mpfr_ieee_double in
+ 0) AC_MSG_RESULT(no)
+ AC_MSG_ERROR([unknown 'double' format]) ;;
+ *) AC_MSG_RESULT(yes)
+ esac
],
[AC_MSG_RESULT(no)
AC_MSG_ERROR([Compiler doesn't know _Decimal64 (ISO/IEC TR 24732).
diff --git a/src/mpfr-gmp.h b/src/mpfr-gmp.h
index 445b35338..267375ebb 100644
--- a/src/mpfr-gmp.h
+++ b/src/mpfr-gmp.h
@@ -405,6 +405,69 @@ typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into
} \
} while (0)
+/* ieee_double_extract structure (copied from GMP 6.1.0, gmp-impl.h) */
+
+/* Define ieee_double_extract and _GMP_IEEE_FLOATS.
+
+ Bit field packing is "implementation defined" according to C99, which
+ leaves us at the compiler's mercy here. For some systems packing is
+ defined in the ABI (eg. x86). In any case so far it seems universal that
+ little endian systems pack from low to high, and big endian from high to
+ low within the given type.
+
+ Within the fields we rely on the integer endianness being the same as the
+ float endianness, this is true everywhere we know of and it'd be a fairly
+ strange system that did anything else. */
+
+#ifndef _GMP_IEEE_FLOATS
+
+#if HAVE_DOUBLE_IEEE_LITTLE_SWAPPED
+#define _GMP_IEEE_FLOATS 1
+union ieee_double_extract
+{
+ struct
+ {
+ unsigned long manh:20;
+ unsigned long exp:11;
+ unsigned long sig:1;
+ unsigned long manl:32;
+ } s;
+ double d;
+};
+#endif
+
+#if HAVE_DOUBLE_IEEE_LITTLE_ENDIAN
+#define _GMP_IEEE_FLOATS 1
+union ieee_double_extract
+{
+ struct
+ {
+ unsigned long manl:32;
+ unsigned long manh:20;
+ unsigned long exp:11;
+ unsigned long sig:1;
+ } s;
+ double d;
+};
+#endif
+
+#if HAVE_DOUBLE_IEEE_BIG_ENDIAN
+#define _GMP_IEEE_FLOATS 1
+union ieee_double_extract
+{
+ struct
+ {
+ unsigned long sig:1;
+ unsigned long exp:11;
+ unsigned long manh:20;
+ unsigned long manl:32;
+ } s;
+ double d;
+};
+#endif
+
+#endif /* _GMP_IEEE_FLOATS */
+
#if defined (__cplusplus)
}
#endif