summaryrefslogtreecommitdiff
path: root/set_ld.c
diff options
context:
space:
mode:
authorryde <ryde@280ebfd0-de03-0410-8827-d642c229c3f4>2003-01-14 22:48:03 +0000
committerryde <ryde@280ebfd0-de03-0410-8827-d642c229c3f4>2003-01-14 22:48:03 +0000
commit0f576f9ce401ea77d21c8cd7727756f9ee0b8588 (patch)
tree02c04ac07ced03380b636e381bf282215e28d71f /set_ld.c
parent57892abf1bd25b5d48ed6e5a54a37b74ff64e5c6 (diff)
downloadmpfr-0f576f9ce401ea77d21c8cd7727756f9ee0b8588.tar.gz
Avoid problems with bad LDBL_MAX and LDBL_MANT_DIG on some i386 gcc.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2163 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'set_ld.c')
-rw-r--r--set_ld.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/set_ld.c b/set_ld.c
index d1aaa0a33..d6c391810 100644
--- a/set_ld.c
+++ b/set_ld.c
@@ -21,20 +21,46 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <float.h>
+#include <limits.h> /* for CHAR_BIT */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
#include "mpfr-impl.h"
-#ifndef LDBL_MANT_DIG
-#define LDBL_MANT_DIG 113 /* works also if long double == quad */
-#endif
-
#ifndef DBL_MANT_DIG
#define DBL_MANT_DIG 53
#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+
+/* Various i386 systems have been seen with float.h LDBL constants equal to
+ the DBL ones, whereas they ought to be bigger, reflecting the 10-byte
+ IEEE extended format on that processor. gcc 3.2.1 on FreeBSD and Solaris
+ has been seen with the problem, and gcc 2.95.4 on FreeBSD 4.7. */
+
+#if HAVE_LDOUBLE_IEEE_EXT_LITTLE
+static const struct {
+ char bytes[10];
+ long double dummy; /* for memory alignment */
+} ldbl_max_struct = {
+ { '\xFF','\xFF','\xFF','\xFF',
+ '\xFF','\xFF','\xFF','\xFF',
+ '\xFE','\x7F' }
+};
+#define MPFR_LDBL_MAX (* (const long double *) ldbl_max_struct.bytes)
+#else
+#define MPFR_LDBL_MAX LDBL_MAX
+#endif
+
+/* This is an overestimate, but fine for our purposes, it only needs to be
+ enough that "t" below can hold a long double without rounding. */
+#define MPFR_LDBL_MANT_DIG (CHAR_BIT * sizeof (long double))
+
+
int
mpfr_set_ld (mpfr_ptr r, long double d, mp_rnd_t rnd_mode)
{
@@ -47,13 +73,13 @@ mpfr_set_ld (mpfr_ptr r, long double d, mp_rnd_t rnd_mode)
MPFR_RET_NAN;
}
- if (d > LDBL_MAX)
+ if (d > MPFR_LDBL_MAX)
{
mpfr_set_inf (r, 1);
return 0;
}
- if (d < -LDBL_MAX)
+ if (d < -MPFR_LDBL_MAX)
{
mpfr_set_inf (r, -1);
return 0;
@@ -62,7 +88,7 @@ mpfr_set_ld (mpfr_ptr r, long double d, mp_rnd_t rnd_mode)
if (d == 0.0)
return mpfr_set_d (r, (double) d, rnd_mode);
- mpfr_init2 (t, LDBL_MANT_DIG);
+ mpfr_init2 (t, MPFR_LDBL_MANT_DIG);
mpfr_init2 (u, DBL_MANT_DIG);
mpfr_set_ui (t, 0, GMP_RNDN);
while (d != 0.0)