summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2021-03-09 12:45:39 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2021-03-09 12:45:39 +0000
commitbeb5a38f955fcee098d298e7afde6c3aab040388 (patch)
tree160fc34a6ed9767fd0cf5d452186c6ff0028dd57
parent618351b9a051e1a6fa3c5a1b40afc7ae2ba3b7cf (diff)
downloadmpfr-beb5a38f955fcee098d298e7afde6c3aab040388.tar.gz
In mpfr.h, fixed some macros implementing functions. Added tests.
* src/mpfr.h: - Macros mpfr_nan_p, mpfr_inf_p, mpfr_zero_p, mpfr_regular_p, mpfr_get_prec, mpfr_get_exp, mpfr_copysign and mpfr_signbit yielded a compilation error when the argument (the 3rd one for mpfr_copysign) was of type void *, for instance. - Macro mpfr_set had the same issue with the 2nd argument, but also evaluated this argument twice. The fix was possible only with a GNU extension. Thus this macro is available only with GCC and compatible compilers (see __GNUC__); otherwise, the mpfr_set function is used. * src/ubf.c: added a missing cast (this issue became visible with the fix of the mpfr_get_prec macro). * tests/mpfr-test.h: added macros for the new tests (tests with void * arguments are invalid in C++ and they trigger a warning with GCC's -Wc++-compat, so we need to avoid these issues). * tests/*.c: added tests to check that some calls (potentially macros) behave like function calls. In detail: - tcopysign.c: mpfr_copysign and mpfr_setsign. - texceptions.c: mpfr_get_prec. - tisnan.c: mpfr_nan_p, mpfr_inf_p, mpfr_number_p (though not currently concerned here), mpfr_zero_p and mpfr_regular_p. - tset.c: mpfr_set. - tset_exp.c: mpfr_get_exp. * doc/mpfr.texi: added some text in Section "Custom Interface" to clarify the usage of macros for this interface. (merged changesets r14447-14463 from the trunk) git-svn-id: https://scm.gforge.inria.fr/anonscm/svn/mpfr/branches/4.1@14469 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--doc/mpfr.texi6
-rw-r--r--src/mpfr.h52
-rw-r--r--src/ubf.c2
-rw-r--r--tests/mpfr-test.h26
-rw-r--r--tests/tcopysign.c43
-rw-r--r--tests/texceptions.c18
-rw-r--r--tests/tisnan.c115
-rw-r--r--tests/tset.c61
-rw-r--r--tests/tset_exp.c12
9 files changed, 260 insertions, 75 deletions
diff --git a/doc/mpfr.texi b/doc/mpfr.texi
index 8924ad255..846cb27cd 100644
--- a/doc/mpfr.texi
+++ b/doc/mpfr.texi
@@ -3817,6 +3817,12 @@ to the application.
Each function in this interface is also implemented as a macro for
efficiency reasons: for example @code{mpfr_custom_init (s, p)}
uses the macro, while @code{(mpfr_custom_init) (s, p)} uses the function.
+Note that the macro may evaluate arguments multiple times (or none).
+Moreover, macros implementing functions with the @code{void} return type
+may not be used in contexts where an expression is expected, e.g., inside
+@code{for(...)} or before a comma operator.
+@c These limitations with macros cannot be avoided in a C90 compatible way.
+@c In the future, inline functions could be used.
Note 1: MPFR functions may still initialize temporary floating-point numbers
using @code{mpfr_init} and similar functions. See Custom Allocation (GNU MP)@.
diff --git a/src/mpfr.h b/src/mpfr.h
index beea0c605..f7a247608 100644
--- a/src/mpfr.h
+++ b/src/mpfr.h
@@ -833,23 +833,39 @@ __MPFR_DECLSPEC int mpfr_total_order_p (mpfr_srcptr, mpfr_srcptr);
even if it produces faster and smaller code. */
#ifndef MPFR_USE_NO_MACRO
-/* Inlining these functions is both faster and smaller */
-#define mpfr_nan_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_NAN)
-#define mpfr_inf_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_INF)
-#define mpfr_zero_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_ZERO)
-#define mpfr_regular_p(_x) ((_x)->_mpfr_exp > __MPFR_EXP_INF)
+/* In the implementation of these macros, we need to make sure that the
+ arguments are evaluated one time exactly and that type conversion is
+ done as it would be with a function. Tests should be added to ensure
+ that.
+ Note that the macros for the custom interface are not concerned; the
+ MPFR manual has been clarified. */
+
+/* Prevent x from being used as an lvalue.
+ Thanks to Wojtek Lerch and Tim Rentsch for the idea. */
+#define MPFR_VALUE_OF(x) (0 ? (x) : (x))
+
+/* The following macro converts the argument to mpfr_srcptr, as in type
+ conversion for function parameters. But it will detect disallowed
+ implicit conversions, e.g. when the argument has an integer type. */
+#define MPFR_SRCPTR(x) ((mpfr_srcptr) (0 ? (x) : (mpfr_srcptr) (x)))
+#define MPFR_GET_SIGN(_x) MPFR_VALUE_OF(MPFR_SIGN(MPFR_SRCPTR(_x)))
+
+#define mpfr_nan_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_NAN)
+#define mpfr_inf_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_INF)
+#define mpfr_zero_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_ZERO)
+#define mpfr_regular_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp > __MPFR_EXP_INF)
+
+/* mpfr_sgn is documented as a macro, thus the following code is fine.
+ But it would be safer to regard it as a function in some future
+ MPFR version. */
#define mpfr_sgn(_x) \
((_x)->_mpfr_exp < __MPFR_EXP_INF ? \
(mpfr_nan_p (_x) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : \
MPFR_SIGN (_x))
-/* Prevent them from using as lvalues */
-#define MPFR_VALUE_OF(x) (0 ? (x) : (x))
-#define mpfr_get_prec(_x) MPFR_VALUE_OF((_x)->_mpfr_prec)
-#define mpfr_get_exp(_x) MPFR_VALUE_OF((_x)->_mpfr_exp)
-/* Note 1: If need be, the MPFR_VALUE_OF can be used for other expressions
- (of any type). Thanks to Wojtek Lerch and Tim Rentsch for the idea.
- Note 2: Defining mpfr_get_exp() as a macro has the effect to disable
+#define mpfr_get_prec(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_prec)
+#define mpfr_get_exp(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_exp)
+/* Note: Defining mpfr_get_exp() as a macro has the effect to disable
the check that the argument is a pure FP number (done in the function);
this increases the risk of undetected error and makes debugging more
complex. Is it really worth in practice? (Potential FIXME) */
@@ -861,11 +877,17 @@ __MPFR_DECLSPEC int mpfr_total_order_p (mpfr_srcptr, mpfr_srcptr);
#define mpfr_cmp_ui(b,i) mpfr_cmp_ui_2exp((b),(i),0)
#define mpfr_cmp_si(b,i) mpfr_cmp_si_2exp((b),(i),0)
-#define mpfr_set(a,b,r) mpfr_set4(a,b,r,MPFR_SIGN(b))
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
+#define mpfr_set(a,b,r) \
+ __extension__ ({ \
+ mpfr_srcptr _p = (b); \
+ mpfr_set4(a,_p,r,MPFR_SIGN(_p)); \
+ })
+#endif
#define mpfr_abs(a,b,r) mpfr_set4(a,b,r,1)
-#define mpfr_copysign(a,b,c,r) mpfr_set4(a,b,r,MPFR_SIGN(c))
+#define mpfr_copysign(a,b,c,r) mpfr_set4(a,b,r,MPFR_GET_SIGN(c))
#define mpfr_setsign(a,b,s,r) mpfr_set4(a,b,r,(s) ? -1 : 1)
-#define mpfr_signbit(x) (MPFR_SIGN(x) < 0)
+#define mpfr_signbit(x) (MPFR_GET_SIGN(x) < 0)
#define mpfr_cmp(b, c) mpfr_cmp3(b, c, 1)
#define mpfr_mul_2exp(y,x,n,r) mpfr_mul_2ui((y),(x),(n),(r))
#define mpfr_div_2exp(y,x,n,r) mpfr_div_2ui((y),(x),(n),(r))
diff --git a/src/ubf.c b/src/ubf.c
index ec6070d34..492a4e5b9 100644
--- a/src/ubf.c
+++ b/src/ubf.c
@@ -78,7 +78,7 @@ mpfr_ubf_mul_exact (mpfr_ubf_ptr a, mpfr_srcptr b, mpfr_srcptr c)
mpfr_get_prec (b), mpfr_log_prec, b,
mpfr_get_prec (c), mpfr_log_prec, c),
("a[%Pu]=%.*Rg",
- mpfr_get_prec (a), mpfr_log_prec, a));
+ mpfr_get_prec ((mpfr_ptr) a), mpfr_log_prec, a));
MPFR_ASSERTD ((mpfr_ptr) a != b);
MPFR_ASSERTD ((mpfr_ptr) a != c);
diff --git a/tests/mpfr-test.h b/tests/mpfr-test.h
index 0103e8ba9..f9d7d3059 100644
--- a/tests/mpfr-test.h
+++ b/tests/mpfr-test.h
@@ -92,6 +92,32 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define STRINGIZE(S) #S
#define MAKE_STR(S) STRINGIZE(S)
+/* In C (but not C++), mpfr_ptr and mpfr_srcptr arguments can be provided
+ in a different pointer type, such as void *. For functions implemented
+ as macros, the type conversion for the function parameters will not be
+ done by the compiler, which means potential bugs in these implementations
+ if we forget to take these unusual cases into account. So we need to test
+ such arguments, in order to make sure that the arguments are converted to
+ the expected type when needed.
+
+ However, at least when the function is not implemented as a macro (which
+ is the case when MPFR_USE_NO_MACRO is defined), such tests with void *
+ arguments are not valid in C++; therefore, we will not do the cast to
+ void * if the __cplusplus macro is defined. And with GCC compilers (and
+ compatible), we will ignore the -Wc++-compat option around these tests.
+
+ Note: in the future, inline functions could be used instead of macros,
+ and such tests would become useless (except to detect compiler bugs).
+*/
+#if defined (__cplusplus)
+#define VOIDP_CAST(X) (X)
+#else
+#define VOIDP_CAST(X) ((void *) (X))
+#if defined (__GNUC__)
+#define IGNORE_CPP_COMPAT
+#endif
+#endif
+
#if defined (__cplusplus)
extern "C" {
#endif
diff --git a/tests/tcopysign.c b/tests/tcopysign.c
index 354f6ad2d..0c1cc428e 100644
--- a/tests/tcopysign.c
+++ b/tests/tcopysign.c
@@ -27,16 +27,17 @@ copysign_variant (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
mpfr_rnd_t rnd_mode, int k)
{
mpfr_srcptr p;
+ int a = 0, b = 0, c = 0;
/* invalid sign, to test that the sign is always correctly set */
MPFR_SIGN (z) = 0;
- if (k >= 6)
+ if (k >= 8)
{
MPFR_ASSERTN (MPFR_PREC (z) >= MPFR_PREC (x));
mpfr_set (z, x, MPFR_RNDN);
p = z;
- k -= 6;
+ k -= 8;
}
else
p = x;
@@ -51,17 +52,47 @@ copysign_variant (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
(mpfr_copysign) (z, p, y, rnd_mode);
return;
case 2:
- mpfr_setsign (z, p, mpfr_signbit (y), rnd_mode);
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+ mpfr_copysign ((a++, VOIDP_CAST(z)),
+ (b++, VOIDP_CAST(p)),
+ (c++, VOIDP_CAST(y)), rnd_mode);
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
+ MPFR_ASSERTN (a == 1);
+ MPFR_ASSERTN (b == 1);
+ MPFR_ASSERTN (c == 1);
return;
case 3:
- mpfr_setsign (z, p, (mpfr_signbit) (y), rnd_mode);
+ mpfr_setsign (z, p, mpfr_signbit (y), rnd_mode);
return;
case 4:
- (mpfr_setsign) (z, p, mpfr_signbit (y), rnd_mode);
+ mpfr_setsign (z, p, (mpfr_signbit) (y), rnd_mode);
return;
case 5:
+ (mpfr_setsign) (z, p, mpfr_signbit (y), rnd_mode);
+ return;
+ case 6:
(mpfr_setsign) (z, p, (mpfr_signbit) (y), rnd_mode);
return;
+ case 7:
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+ mpfr_setsign ((a++, VOIDP_CAST(z)),
+ (b++, VOIDP_CAST(p)),
+ mpfr_signbit ((c++, VOIDP_CAST(y))), rnd_mode);
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
+ MPFR_ASSERTN (a == 1);
+ MPFR_ASSERTN (b == 1);
+ MPFR_ASSERTN (c == 1);
+ return;
}
}
@@ -79,7 +110,7 @@ main (void)
for (i = 0; i <= 1; i++)
for (j = 0; j <= 1; j++)
- for (k = 0; k < 12; k++)
+ for (k = 0; k < 16; k++)
{
mpfr_set_nan (x);
i ? MPFR_SET_NEG (x) : MPFR_SET_POS (x);
diff --git a/tests/texceptions.c b/tests/texceptions.c
index d718fe66a..7159737fb 100644
--- a/tests/texceptions.c
+++ b/tests/texceptions.c
@@ -103,10 +103,26 @@ static void
check_get_prec (void)
{
mpfr_t x;
+ int i = 0;
mpfr_init2 (x, 17);
- if (mpfr_get_prec (x) != 17 || (mpfr_get_prec)(x) != 17)
+
+ if (mpfr_get_prec (x) != 17 || (mpfr_get_prec) (x) != 17)
PRINT_ERROR ("mpfr_get_prec");
+
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+
+ if (mpfr_get_prec ((i++, VOIDP_CAST(x))) != 17)
+ PRINT_ERROR ("mpfr_get_prec (2)");
+
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
+
+ MPFR_ASSERTN (i == 1);
mpfr_clear (x);
}
diff --git a/tests/tisnan.c b/tests/tisnan.c
index 72908b1ea..550f7828f 100644
--- a/tests/tisnan.c
+++ b/tests/tisnan.c
@@ -27,180 +27,235 @@ int
main (void)
{
mpfr_t x;
+ int i = 0, j = 0;
+
+ /* We need to check that when the function is implemented by a macro,
+ it behaves correctly. */
+#define ARG (i++, VOIDP_CAST(x))
+#define CHECK MPFR_ASSERTN (i == ++j)
tests_start_mpfr ();
mpfr_init (x);
+#if 0
+ /* The following should yield a compilation error when the functions
+ are implemented as macros. Change 0 to 1 above in order to test. */
+ (void) (mpfr_nan_p (1L));
+ (void) (mpfr_inf_p (1L));
+ (void) (mpfr_number_p (1L));
+ (void) (mpfr_zero_p (1L));
+ (void) (mpfr_regular_p (1L));
+#endif
+
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+
/* check +infinity gives non-zero for mpfr_inf_p only */
mpfr_set_ui (x, 1L, MPFR_RNDZ);
mpfr_div_ui (x, x, 0L, MPFR_RNDZ);
- if (mpfr_nan_p (x) || (mpfr_nan_p) (x) )
+ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(+Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_inf_p (x) == 0)
+ CHECK;
+ if (!mpfr_inf_p (x) || !(mpfr_inf_p) (x) || !mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(+Inf) gives zero\n");
exit (1);
}
- if (mpfr_number_p (x) || (mpfr_number_p) (x) )
+ CHECK;
+ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(+Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_zero_p (x) || (mpfr_zero_p) (x) )
+ CHECK;
+ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
{
printf ("Error: mpfr_zero_p(+Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
+ CHECK;
+ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(+Inf) gives non-zero\n");
exit (1);
}
+ CHECK;
/* same for -Inf */
mpfr_neg (x, x, MPFR_RNDN);
- if (mpfr_nan_p (x) || (mpfr_nan_p(x)))
+ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(-Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_inf_p (x) == 0)
+ CHECK;
+ if (!mpfr_inf_p (x) || !(mpfr_inf_p) (x) || !mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(-Inf) gives zero\n");
exit (1);
}
- if (mpfr_number_p (x) || (mpfr_number_p)(x) )
+ CHECK;
+ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(-Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_zero_p (x) || (mpfr_zero_p)(x) )
+ CHECK;
+ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
{
printf ("Error: mpfr_zero_p(-Inf) gives non-zero\n");
exit (1);
}
- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
+ CHECK;
+ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(-Inf) gives non-zero\n");
exit (1);
}
+ CHECK;
/* same for NaN */
mpfr_sub (x, x, x, MPFR_RNDN);
- if (mpfr_nan_p (x) == 0)
+ if (!mpfr_nan_p (x) || !(mpfr_nan_p) (x) || !mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(NaN) gives zero\n");
exit (1);
}
- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
+ CHECK;
+ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(NaN) gives non-zero\n");
exit (1);
}
- if (mpfr_number_p (x) || (mpfr_number_p) (x) )
+ CHECK;
+ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(NaN) gives non-zero\n");
exit (1);
}
- if (mpfr_zero_p (x) || (mpfr_zero_p)(x) )
+ CHECK;
+ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
{
printf ("Error: mpfr_number_p(NaN) gives non-zero\n");
exit (1);
}
- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
+ CHECK;
+ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(NaN) gives non-zero\n");
exit (1);
}
+ CHECK;
/* same for a regular number */
mpfr_set_ui (x, 1, MPFR_RNDN);
- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
+ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(1) gives non-zero\n");
exit (1);
}
- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
+ CHECK;
+ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(1) gives non-zero\n");
exit (1);
}
- if (mpfr_number_p (x) == 0)
+ CHECK;
+ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(1) gives zero\n");
exit (1);
}
- if (mpfr_zero_p (x) || (mpfr_zero_p) (x) )
+ CHECK;
+ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
{
printf ("Error: mpfr_zero_p(1) gives non-zero\n");
exit (1);
}
- if (mpfr_regular_p (x) == 0 || (mpfr_regular_p) (x) == 0)
+ CHECK;
+ if (!mpfr_regular_p (x) || !(mpfr_regular_p) (x) || !mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(1) gives zero\n");
exit (1);
}
+ CHECK;
/* Same for +0 */
mpfr_set_ui (x, 0, MPFR_RNDN);
- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
+ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(+0) gives non-zero\n");
exit (1);
}
- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
+ CHECK;
+ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(+0) gives non-zero\n");
exit (1);
}
- if (mpfr_number_p (x) == 0)
+ CHECK;
+ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(+0) gives zero\n");
exit (1);
}
- if (mpfr_zero_p (x) == 0 )
+ CHECK;
+ if (!mpfr_zero_p (x) || !(mpfr_zero_p) (x) || !mpfr_zero_p (ARG))
{
printf ("Error: mpfr_zero_p(+0) gives zero\n");
exit (1);
}
- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
+ CHECK;
+ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(+0) gives non-zero\n");
exit (1);
}
+ CHECK;
/* Same for -0 */
mpfr_set_ui (x, 0, MPFR_RNDN);
mpfr_neg (x, x, MPFR_RNDN);
- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
+ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
{
printf ("Error: mpfr_nan_p(-0) gives non-zero\n");
exit (1);
}
- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
+ CHECK;
+ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
{
printf ("Error: mpfr_inf_p(-0) gives non-zero\n");
exit (1);
}
- if (mpfr_number_p (x) == 0)
+ CHECK;
+ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
{
printf ("Error: mpfr_number_p(-0) gives zero\n");
exit (1);
}
- if (mpfr_zero_p (x) == 0 )
+ CHECK;
+ if (!mpfr_zero_p (x) || !(mpfr_zero_p) (x) || !mpfr_zero_p (ARG))
{
printf ("Error: mpfr_zero_p(-0) gives zero\n");
exit (1);
}
- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
+ CHECK;
+ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
{
printf ("Error: mpfr_regular_p(-0) gives non-zero\n");
exit (1);
}
+ CHECK;
+
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
mpfr_clear (x);
diff --git a/tests/tset.c b/tests/tset.c
index ebf10383d..e5ef65f09 100644
--- a/tests/tset.c
+++ b/tests/tset.c
@@ -207,7 +207,7 @@ check_special (void)
static void
check_ternary_value (void)
{
- int p, q, rnd;
+ int k, p, q, rnd;
int inexact, cmp;
mpfr_t x, y;
@@ -226,28 +226,45 @@ check_ternary_value (void)
{
if (rnd == MPFR_RNDF) /* the test below makes no sense */
continue;
- inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
- cmp = mpfr_cmp (y, x);
- if (((inexact == 0) && (cmp != 0)) ||
- ((inexact > 0) && (cmp <= 0)) ||
- ((inexact < 0) && (cmp >= 0)))
+ for (k = 0; k < 3; k++)
{
- printf ("Wrong ternary value in mpfr_set for %s: expected"
- " %d, got %d\n",
- mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), cmp,
- inexact);
- exit (1);
- }
- /* Test mpfr_set function too */
- inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
- cmp = mpfr_cmp (y, x);
- if (((inexact == 0) && (cmp != 0)) ||
- ((inexact > 0) && (cmp <= 0)) ||
- ((inexact < 0) && (cmp >= 0)))
- {
- printf ("Wrong ternary value in mpfr_set(2): expected %d,"
- " got %d\n", cmp, inexact);
- exit (1);
+ int a = 0, b = 0, c = 0;
+
+ switch (k)
+ {
+ case 0:
+ inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
+ break;
+ case 1:
+ inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
+ break;
+ case 2:
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+ inexact = mpfr_set ((a++, VOIDP_CAST(y)),
+ (b++, VOIDP_CAST(x)),
+ (c++, (mpfr_rnd_t) rnd));
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
+ MPFR_ASSERTN (a == 1);
+ MPFR_ASSERTN (b == 1);
+ MPFR_ASSERTN (c == 1);
+ break;
+ }
+ cmp = mpfr_cmp (y, x);
+ if (((inexact == 0) && (cmp != 0)) ||
+ ((inexact > 0) && (cmp <= 0)) ||
+ ((inexact < 0) && (cmp >= 0)))
+ {
+ printf ("Wrong ternary value in mpfr_set for %s (%d):"
+ " expected %d, got %d\n",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
+ k, cmp, inexact);
+ exit (1);
+ }
}
}
}
diff --git a/tests/tset_exp.c b/tests/tset_exp.c
index 15aba16cb..c259a8c94 100644
--- a/tests/tset_exp.c
+++ b/tests/tset_exp.c
@@ -28,6 +28,7 @@ main (int argc, char *argv[])
mpfr_t x;
int ret;
mpfr_exp_t emin, emax, e;
+ int i = 0;
tests_start_mpfr ();
@@ -63,6 +64,17 @@ main (int argc, char *argv[])
e = (mpfr_get_exp) (x);
MPFR_ASSERTN (e == emin);
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+ e = mpfr_get_exp ((i++, VOIDP_CAST(x)));
+#ifdef IGNORE_CPP_COMPAT
+#pragma GCC diagnostic pop
+#endif
+ MPFR_ASSERTN (e == emin);
+ MPFR_ASSERTN (i == 1);
+
ret = mpfr_set_exp (x, -1);
MPFR_ASSERTN (ret == 0 && mpfr_cmp_ui_2exp (x, 1, -2) == 0);