summaryrefslogtreecommitdiff
path: root/acinclude.m4
diff options
context:
space:
mode:
authorryde <ryde@280ebfd0-de03-0410-8827-d642c229c3f4>2003-01-14 22:43:24 +0000
committerryde <ryde@280ebfd0-de03-0410-8827-d642c229c3f4>2003-01-14 22:43:24 +0000
commit57892abf1bd25b5d48ed6e5a54a37b74ff64e5c6 (patch)
tree2508742355a9aa5bab04eafa303ae9c18c19b2f9 /acinclude.m4
parent77c4469268caa6bec3327f0da08bfeefc548d03c (diff)
downloadmpfr-57892abf1bd25b5d48ed6e5a54a37b74ff64e5c6.tar.gz
(MPFR_C_LONG_DOUBLE_FORMAT): New macro.
(MPFR_CONFIGS): Use it. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2162 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'acinclude.m4')
-rw-r--r--acinclude.m4208
1 files changed, 208 insertions, 0 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index 32614108d..8e152dad1 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -197,4 +197,212 @@ if test "$mpfr_cv_have_huge_val" = "yes"; then
AC_DEFINE(HAVE_HUGE_VAL,1,[Define if HUGE_VAL can be used without the need of a specific library.])
fi
+MPFR_C_LONG_DOUBLE_FORMAT
+])
+
+
+dnl MPFR_C_LONG_DOUBLE_FORMAT
+dnl -------------------------
+dnl Determine the format of a long double.
+dnl
+dnl The object file is grepped, so as to work when cross compiling. A
+dnl start and end sequence is included to avoid false matches, and
+dnl allowance is made for the desired data crossing an "od -b" line
+dnl boundary. The test number is a small integer so it should appear
+dnl exactly, no rounding or truncation etc.
+dnl
+dnl "od -b" is supported even by Unix V7, and the awk script used doesn't
+dnl have functions or anything, so even an "old" awk should suffice.
+dnl
+dnl The 10-byte IEEE extended format is normally padded to either 12 or 16
+dnl bytes, for alignment purposes. The SVR4 i386 ABI is 12 bytes, or i386
+dnl gcc -m128bit-long-double can select 16 bytes. IA-64 is 16 bytes in
+dnl LP64 mode, or 12 bytes in ILP32 mode. The first 10 bytes are the
+dnl relevant data, even in IA-64 big-endian mode too.
+dnl
+dnl Enhancements:
+dnl
+dnl Could match more formats (IEEE quad, or big endian IEEE), but no need
+dnl to worry until there's code wanting to use them.
+dnl
+dnl Don't want to duplicate the double matching from GMP_C_DOUBLE_FORMAT,
+dnl perhaps we should merge with that macro, to match data formats
+dnl irrespective of the C type in question. Or perhaps just let the code
+dnl use DOUBLE macros when sizeof(double)==sizeof(long double).
+
+AC_DEFUN(MPFR_C_LONG_DOUBLE_FORMAT,
+[AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_AWK])
+AC_CACHE_CHECK([format of `long double' floating point],
+ mpfr_cv_c_long_double_format,
+[mpfr_cv_c_long_double_format=unknown
+cat >conftest.c <<\EOF
+[
+/* "before" is 16 bytes to ensure there's no padding between it and "x".
+ We're not expecting any "long double" bigger than 16 bytes or with
+ alignment requirements stricter than 16 bytes. */
+struct {
+ char before[16];
+ long double x;
+ char after[8];
+} foo = {
+ { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\x01', '\x23', '\x45', '\x67', '\x89', '\xAB', '\xCD', '\xEF' },
+ -123456789.0,
+ { '\xFE', '\xDC', '\xBA', '\x98', '\x76', '\x54', '\x32', '\x10' },
+};
+]
+EOF
+mpfr_compile="$CC $CFLAGS $CPPFLAGS -c conftest.c >&AC_FD_CC 2>&1"
+if AC_TRY_EVAL(mpfr_compile); then
+cat >conftest.awk <<\EOF
+[
+BEGIN {
+ found = 0
+}
+
+# got[] holds a sliding window of bytes read the input. got[0] is the most
+# recent byte read, and got[31] the oldest byte read, so when looking to
+# match some data the indices are "reversed".
+#
+{
+ for (f = 2; f <= NF; f++)
+ {
+ # new byte, shift others up
+ for (i = 31; i >= 0; i--)
+ got[i+1] = got[i];
+ got[0] = $f;
+
+ # end sequence
+ if (got[7] != "376") continue
+ if (got[6] != "334") continue
+ if (got[5] != "272") continue
+ if (got[4] != "230") continue
+ if (got[3] != "166") continue
+ if (got[2] != "124") continue
+ if (got[1] != "062") continue
+ if (got[0] != "020") continue
+
+ # start sequence, with 12-byte body
+ if (got[27] == "001" && \
+ got[26] == "043" && \
+ got[25] == "105" && \
+ got[24] == "147" && \
+ got[23] == "211" && \
+ got[22] == "253" && \
+ got[21] == "315" && \
+ got[20] == "357")
+ {
+ saw = " (" got[19] \
+ " " got[18] \
+ " " got[17] \
+ " " got[16] \
+ " " got[15] \
+ " " got[14] \
+ " " got[13] \
+ " " got[12] \
+ " " got[11] \
+ " " got[10] \
+ " " got[9] \
+ " " got[8] ")"
+
+ if (got[19] == "000" && \
+ got[18] == "000" && \
+ got[17] == "000" && \
+ got[16] == "000" && \
+ got[15] == "240" && \
+ got[14] == "242" && \
+ got[13] == "171" && \
+ got[12] == "353" && \
+ got[11] == "031" && \
+ got[10] == "300")
+ {
+ print "IEEE extended, little endian"
+ found = 1
+ exit
+ }
+ }
+
+ # start sequence, with 16-byte body
+ if (got[31] == "001" && \
+ got[30] == "043" && \
+ got[29] == "105" && \
+ got[28] == "147" && \
+ got[27] == "211" && \
+ got[26] == "253" && \
+ got[25] == "315" && \
+ got[24] == "357")
+ {
+ saw = " (" got[23] \
+ " " got[22] \
+ " " got[21] \
+ " " got[20] \
+ " " got[19] \
+ " " got[18] \
+ " " got[17] \
+ " " got[16] \
+ " " got[15] \
+ " " got[14] \
+ " " got[13] \
+ " " got[12] \
+ " " got[11] \
+ " " got[10] \
+ " " got[9] \
+ " " got[8] ")"
+
+ if (got[23] == "000" && \
+ got[22] == "000" && \
+ got[21] == "000" && \
+ got[20] == "000" && \
+ got[19] == "240" && \
+ got[18] == "242" && \
+ got[17] == "171" && \
+ got[16] == "353" && \
+ got[15] == "031" && \
+ got[14] == "300")
+ {
+ print "IEEE extended, little endian"
+ found = 1
+ exit
+ }
+ }
+ }
+}
+
+END {
+ if (! found)
+ print "unknown", saw
+}
+]
+EOF
+ mpfr_cv_c_long_double_format=`od -b conftest.$OBJEXT | $AWK -f conftest.awk`
+ case $mpfr_cv_c_long_double_format in
+ unknown*)
+ echo "cannot match anything, conftest.$OBJEXT contains" >&AC_FD_CC
+ od -b conftest.$OBJEXT >&AC_FD_CC
+ ;;
+ esac
+else
+ AC_MSG_WARN([oops, cannot compile test program])
+fi
+])
+
+AH_VERBATIM([HAVE_LDOUBLE],
+[/* Define one of the following to 1 for the format of a `long double'.
+ If your format is not among these choices, or you don't know what it is,
+ then leave all undefined.
+ IEEE_EXT is the 10-byte IEEE extended format.
+ LITTLE or BIG is the endianness. */
+#undef HAVE_LDOUBLE_IEEE_EXT_LITTLE])
+
+case $mpfr_cv_c_long_double_format in
+ "IEEE extended, little endian")
+ AC_DEFINE(HAVE_LDOUBLE_IEEE_EXT_LITTLE, 1)
+ ;;
+ unknown*)
+ ;;
+ *)
+ AC_MSG_WARN([oops, unrecognised float format: $mpfr_cv_c_long_double_format])
+ ;;
+esac
])