summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-09-29 12:27:36 +0000
committerpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-09-29 12:27:36 +0000
commit8eb22ba63830dbf829b9faa742c68438c43992d9 (patch)
tree3482ee8bed089b988aae3d20dda76cede0dab587
parent795c8ef5f9daa924b5592582240c9ba9a58034c1 (diff)
downloadmpfr-8eb22ba63830dbf829b9faa742c68438c43992d9.tar.gz
Add mpfr_clear_erangeflag and mpfr_erangeflag_p.
Add test for theses two functions. mpfr_get_[s/u][i/j] have a deterministic behavior in case of OVERFLOW. (Return the MINIMUM or the MAXIMUM in the current type, and set ERANGE_flag). git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3007 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--exceptions.c16
-rw-r--r--get_si.c12
-rw-r--r--get_sj.c20
-rw-r--r--get_ui.c10
-rw-r--r--get_uj.c18
-rw-r--r--mpfr-impl.h8
-rw-r--r--set_sj.c7
-rw-r--r--set_uj.c7
-rw-r--r--tests/texceptions.c10
-rw-r--r--tests/tget_sj.c76
-rw-r--r--tests/tset_si.c58
-rw-r--r--tests/tset_sj.c7
12 files changed, 237 insertions, 12 deletions
diff --git a/exceptions.c b/exceptions.c
index 8ca0a1e48..a144c0ffa 100644
--- a/exceptions.c
+++ b/exceptions.c
@@ -138,6 +138,14 @@ mpfr_clear_inexflag (void)
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT;
}
+#undef mpfr_clear_erangeflag
+
+void
+mpfr_clear_erangeflag (void)
+{
+ __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
+}
+
#undef mpfr_check_range
int
@@ -200,6 +208,14 @@ mpfr_inexflag_p (void)
return __gmpfr_flags & MPFR_FLAGS_INEXACT;
}
+#undef mpfr_erangeflag_p
+
+int
+mpfr_erangeflag_p (void)
+{
+ return __gmpfr_flags & MPFR_FLAGS_ERANGE;
+}
+
/* #undef mpfr_set_underflow */
/* Note: In the rounding to the nearest mode, mpfr_set_underflow
diff --git a/get_si.c b/get_si.c
index fd55f29eb..5ec6b3e86 100644
--- a/get_si.c
+++ b/get_si.c
@@ -19,7 +19,7 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-
+#include <limits.h>
#include "mpfr-impl.h"
long
@@ -29,8 +29,14 @@ mpfr_get_si (mpfr_srcptr f, mp_rnd_t rnd)
long s;
mpfr_t x;
- if (!mpfr_fits_slong_p (f, rnd) || MPFR_IS_ZERO(f))
- return (long) 0;
+ if (!mpfr_fits_slong_p (f, rnd))
+ {
+ MPFR_SET_ERANGE ();
+ return MPFR_IS_NEG (f) ? LONG_MIN : LONG_MAX;
+ }
+
+ if (MPFR_IS_ZERO (f))
+ return (long) 0;
/* determine prec of long */
for (s = LONG_MIN, prec = 0; s != 0; s /= 2, prec ++);
diff --git a/get_sj.c b/get_sj.c
index 08d1d0106..062f30c38 100644
--- a/get_sj.c
+++ b/get_sj.c
@@ -23,6 +23,13 @@ MA 02111-1307, USA. */
# include "config.h" /* for a build within gmp */
#endif
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined __cplusplus
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
@@ -41,6 +48,14 @@ mpfr_get_sj (mpfr_srcptr f, mpfr_rnd_t rnd)
mp_prec_t prec;
mpfr_t x;
+ if (!mpfr_fits_intmax_p (f, rnd))
+ {
+ MPFR_SET_ERANGE ();
+ return MPFR_IS_NEG (f) ? INTMAX_MIN : INTMAX_MAX;
+ }
+ if (MPFR_IS_ZERO (f))
+ return (intmax_t) 0;
+
/* determine the precision of intmax_t */
for (r = INTMAX_MIN, prec = 0; r != 0; r /= 2, prec++)
{
@@ -63,8 +78,9 @@ mpfr_get_sj (mpfr_srcptr f, mpfr_rnd_t rnd)
xp = MPFR_MANT (x);
sh = MPFR_GET_EXP (x);
- MPFR_ASSERTN (sh <= prec);
- if (INTMAX_MIN + INTMAX_MAX != 0 && MPFR_UNLIKELY (sh == prec))
+ MPFR_ASSERTN ((mp_prec_t) sh <= prec);
+ if (INTMAX_MIN + INTMAX_MAX != 0
+ && MPFR_UNLIKELY ((mp_prec_t) sh == prec))
{
/* 2's complement and x <= INTMAX_MIN: in the case mp_limb_t
has the same size as intmax_t, we cannot use the code in
diff --git a/get_ui.c b/get_ui.c
index 1d5d286d0..cd238b9a5 100644
--- a/get_ui.c
+++ b/get_ui.c
@@ -19,7 +19,7 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-
+#include <limits.h>
#include "mpfr-impl.h"
unsigned long
@@ -31,7 +31,13 @@ mpfr_get_ui (mpfr_srcptr f, mp_rnd_t rnd)
mp_size_t n;
mp_exp_t exp;
- if (!mpfr_fits_ulong_p (f, rnd) || MPFR_IS_ZERO(f))
+ if (!mpfr_fits_ulong_p (f, rnd))
+ {
+ MPFR_SET_ERANGE ();
+ return MPFR_IS_NEG (f) ? 0 : ULONG_MAX;
+ }
+
+ if (MPFR_IS_ZERO (f))
return (unsigned long) 0;
for (s = ULONG_MAX, prec = 0; s != 0; s >>= 1, prec ++);
diff --git a/get_uj.c b/get_uj.c
index 34b700eef..1d1e29042 100644
--- a/get_uj.c
+++ b/get_uj.c
@@ -23,6 +23,13 @@ MA 02111-1307, USA. */
# include "config.h" /* for a build within gmp */
#endif
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined __cplusplus
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
@@ -41,6 +48,15 @@ mpfr_get_uj (mpfr_srcptr f, mpfr_rnd_t rnd)
mp_prec_t prec;
mpfr_t x;
+ if (!mpfr_fits_uintmax_p (f, rnd))
+ {
+ MPFR_SET_ERANGE ();
+ return MPFR_IS_NEG (f) ? (uintmax_t) 0 : UINTMAX_MAX;
+ }
+
+ if (MPFR_IS_ZERO (f))
+ return (uintmax_t) 0;
+
/* determine the precision of uintmax_t */
for (r = UINTMAX_MAX, prec = 0; r != 0; r /= 2, prec++)
{ }
@@ -59,7 +75,7 @@ mpfr_get_uj (mpfr_srcptr f, mpfr_rnd_t rnd)
MPFR_ASSERTN (MPFR_IS_POS (x));
xp = MPFR_MANT (x);
sh = MPFR_GET_EXP (x);
- MPFR_ASSERTN (sh <= prec);
+ MPFR_ASSERTN ((mp_prec_t) sh <= prec);
for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--)
{
sh -= BITS_PER_MP_LIMB;
diff --git a/mpfr-impl.h b/mpfr-impl.h
index 3576b7975..4cc131504 100644
--- a/mpfr-impl.h
+++ b/mpfr-impl.h
@@ -154,11 +154,11 @@ typedef unsigned long int mpfr_uexp_t;
# define mp_exp_unsigned_t mpfr_uexp_t
#endif
-#if MPFR_PREC_FORMAT == 1
+#if _MPFR_PREC_FORMAT == 1
# define MPFR_INTPREC_MAX (USHRT_MAX & ~(unsigned int) (BITS_PER_MP_LIMB - 1))
-#elif MPFR_PREC_FORMAT == 2
+#elif _MPFR_PREC_FORMAT == 2
# define MPFR_INTPREC_MAX (UINT_MAX & ~(unsigned int) (BITS_PER_MP_LIMB - 1))
-#elif MPFR_PREC_FORMAT == 3
+#elif _MPFR_PREC_FORMAT == 3
# define MPFR_INTPREC_MAX (ULONG_MAX & ~(unsigned long) (BITS_PER_MP_LIMB - 1))
#else
# error "Invalid MPFR Prec format"
@@ -473,6 +473,8 @@ long double __gmpfr_longdouble_volatile _MPFR_PROTO ((long double)) ATTRIBUTE_CO
(I) ? ((__gmpfr_flags |= MPFR_FLAGS_INEXACT), (I)) : 0
#define MPFR_RET_NAN return (__gmpfr_flags |= MPFR_FLAGS_NAN), 0
+#define MPFR_SET_ERANGE() (__gmpfr_flags |= MPFR_FLAGS_ERANGE)
+
/* Heap Memory gestion */
typedef union { mp_size_t s; mp_limb_t l; } mpfr_size_limb_t;
#define MPFR_GET_ALLOC_SIZE(x) \
diff --git a/set_sj.c b/set_sj.c
index 509b2a810..f6fa03c49 100644
--- a/set_sj.c
+++ b/set_sj.c
@@ -23,6 +23,13 @@ MA 02111-1307, USA. */
# include "config.h" /* for a build within gmp */
#endif
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined __cplusplus
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
diff --git a/set_uj.c b/set_uj.c
index a8f413fd7..abd06cefa 100644
--- a/set_uj.c
+++ b/set_uj.c
@@ -23,6 +23,13 @@ MA 02111-1307, USA. */
# include "config.h" /* for a build within gmp */
#endif
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined(__cplusplus)
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
diff --git a/tests/texceptions.c b/tests/texceptions.c
index 73e53b3c2..0d99daaec 100644
--- a/tests/texceptions.c
+++ b/tests/texceptions.c
@@ -101,22 +101,32 @@ check_flags (void)
mpfr_mul_2exp (x, x, 1024, GMP_RNDN);
if (!(mpfr_overflow_p)())
ERROR("ERROR: No overflow detected!\n");
+
(mpfr_clear_underflow)();
mpfr_set_ui (x, 1, GMP_RNDN);
mpfr_div_2exp (x, x, 1025, GMP_RNDN);
if (!(mpfr_underflow_p)())
ERROR("ERROR: No underflow detected!\n");
+
(mpfr_clear_nanflag)();
MPFR_SET_NAN(x);
mpfr_add (x, x, x, GMP_RNDN);
if (!(mpfr_nanflag_p)())
ERROR("ERROR: No NaN flag!\n");
+
(mpfr_clear_inexflag)();
mpfr_set_ui(x, 2, GMP_RNDN);
mpfr_cos(x, x, GMP_RNDN);
if (!(mpfr_inexflag_p)())
ERROR("ERROR: No inexact flag!\n");
+ (mpfr_clear_erangeflag) ();
+ mpfr_set_ui (x, 1, GMP_RNDN);
+ mpfr_mul_2exp (x, x, 1024, GMP_RNDN);
+ mpfr_get_ui (x, GMP_RNDN);
+ if (!(mpfr_erangeflag_p)())
+ ERROR ("ERROR: No erange flag!\n");
+
mpfr_clear(x);
}
diff --git a/tests/tget_sj.c b/tests/tget_sj.c
index 869977845..77f3dde5c 100644
--- a/tests/tget_sj.c
+++ b/tests/tget_sj.c
@@ -26,6 +26,13 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined __cplusplus
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
@@ -127,6 +134,73 @@ check_uj (uintmax_t u, mpfr_ptr x)
mpfr_clear (y);
}
+static void
+check_erange (void)
+{
+ mpfr_t x;
+ uintmax_t dl;
+ intmax_t d;
+
+ /* Test for ERANGE flag + correct behaviour if overflow */
+
+ mpfr_init2 (x, 256);
+ mpfr_set_uj (x, UINTMAX_MAX, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ dl = mpfr_get_uj (x, GMP_RNDN);
+ if (dl != UINTMAX_MAX || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (1)\n");
+ exit (1);
+ }
+ mpfr_add_ui (x, x, 1, GMP_RNDN);
+ dl = mpfr_get_uj (x, GMP_RNDN);
+ if (dl != UINTMAX_MAX || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (2)\n");
+ exit (1);
+ }
+ mpfr_set_sj (x, -1, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ dl = mpfr_get_uj (x, GMP_RNDN);
+ if (dl != 0 || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_uj + ERANGE + -1 \n");
+ exit (1);
+ }
+ mpfr_set_sj (x, INTMAX_MAX, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ d = mpfr_get_sj (x, GMP_RNDN);
+ if (d != INTMAX_MAX || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (1)\n");
+ exit (1);
+ }
+ mpfr_add_ui (x, x, 1, GMP_RNDN);
+ d = mpfr_get_sj (x, GMP_RNDN);
+ if (d != INTMAX_MAX || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (2)\n");
+ exit (1);
+ }
+ mpfr_set_sj (x, INTMAX_MIN, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ d = mpfr_get_sj (x, GMP_RNDN);
+ if (d != INTMAX_MIN || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (1)\n");
+ exit (1);
+ }
+ mpfr_sub_ui (x, x, 1, GMP_RNDN);
+ d = mpfr_get_sj (x, GMP_RNDN);
+ if (d != INTMAX_MIN || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (2)\n");
+ exit (1);
+ }
+
+ mpfr_clear (x);
+}
+
int
main (void)
{
@@ -181,6 +255,8 @@ main (void)
mpfr_clear (x);
mpfr_clear (y);
+ check_erange ();
+
tests_end_mpfr ();
return 0;
}
diff --git a/tests/tset_si.c b/tests/tset_si.c
index 342b018d6..9f4771283 100644
--- a/tests/tset_si.c
+++ b/tests/tset_si.c
@@ -79,7 +79,7 @@ main (int argc, char *argv[])
mpfr_init2 (x, 100);
- N = (argc==1) ? 200000 : atol (argv[1]);
+ N = (argc==1) ? 100000 : atol (argv[1]);
for (k = 1; k <= N; k++)
{
@@ -252,6 +252,62 @@ main (int argc, char *argv[])
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
mpfr_set_emax (emax);
+ /* Test for ERANGE flag + correct behaviour if overflow */
+ mpfr_set_prec (x, 256);
+ mpfr_set_ui (x, ULONG_MAX, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ dl = mpfr_get_ui (x, GMP_RNDN);
+ if (dl != ULONG_MAX || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_ui + ERANGE + ULONG_MAX (1)\n");
+ exit (1);
+ }
+ mpfr_add_ui (x, x, 1, GMP_RNDN);
+ dl = mpfr_get_ui (x, GMP_RNDN);
+ if (dl != ULONG_MAX || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_ui + ERANGE + ULONG_MAX (2)\n");
+ exit (1);
+ }
+ mpfr_set_si (x, -1, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ dl = mpfr_get_ui (x, GMP_RNDN);
+ if (dl != 0 || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_ui + ERANGE + -1 \n");
+ exit (1);
+ }
+ mpfr_set_si (x, LONG_MAX, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ d = mpfr_get_si (x, GMP_RNDN);
+ if (d != LONG_MAX || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_si + ERANGE + LONG_MAX (1): %ld\n", d);
+ exit (1);
+ }
+ mpfr_add_ui (x, x, 1, GMP_RNDN);
+ d = mpfr_get_si (x, GMP_RNDN);
+ if (d != LONG_MAX || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_si + ERANGE + LONG_MAX (2)\n");
+ exit (1);
+ }
+ mpfr_set_si (x, LONG_MIN, GMP_RNDN);
+ mpfr_clear_erangeflag ();
+ d = mpfr_get_si (x, GMP_RNDN);
+ if (d != LONG_MIN || mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_si + ERANGE + LONG_MIN (1)\n");
+ exit (1);
+ }
+ mpfr_sub_ui (x, x, 1, GMP_RNDN);
+ d = mpfr_get_si (x, GMP_RNDN);
+ if (d != LONG_MIN || !mpfr_erangeflag_p ())
+ {
+ printf ("ERROR for get_si + ERANGE + LONG_MIN (2)\n");
+ exit (1);
+ }
+
mpfr_clear (x);
test_2exp ();
diff --git a/tests/tset_sj.c b/tests/tset_sj.c
index 4f75f2bcd..c43dbd7c6 100644
--- a/tests/tset_sj.c
+++ b/tests/tset_sj.c
@@ -28,6 +28,13 @@ MA 02111-1307, USA. */
#include <stdlib.h>
#include <limits.h>
+/* The ISO C99 standard specifies that in C++ implementations the
+ INTMAX_MAX, ... macros should only be defined if explicitly requested. */
+#if defined __cplusplus
+# define __STDC_LIMIT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif