summaryrefslogtreecommitdiff
path: root/tests/tfmma.c
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-05-24 09:41:49 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-05-24 09:41:49 +0000
commit491a95a1f4ea6b1c6304092caec65735bee8dc61 (patch)
treed8a584ae381695e4d9b8b7ee150ea090a2b17382 /tests/tfmma.c
parentbdef5b159690e8a614d6897feb1bc9d5cb63bdd8 (diff)
downloadmpfr-491a95a1f4ea6b1c6304092caec65735bee8dc61.tar.gz
[tests/tfmma.c] Added near_overflow_tests, which crashes.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/ubf@10340 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tests/tfmma.c')
-rw-r--r--tests/tfmma.c83
1 files changed, 81 insertions, 2 deletions
diff --git a/tests/tfmma.c b/tests/tfmma.c
index 4140ae05a..d6fcafbaa 100644
--- a/tests/tfmma.c
+++ b/tests/tfmma.c
@@ -22,8 +22,6 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#include "mpfr-test.h"
-/* TODO: add more tests, with special values and exception checking. */
-
/* check both mpfr_fmma and mpfr_fmms */
static void
random_test (mpfr_t a, mpfr_t b, mpfr_t c, mpfr_t d, mpfr_rnd_t rnd)
@@ -222,6 +220,85 @@ max_tests (void)
set_emax (emax);
}
+/* a^2 - (a+k)(a-k) = k^2 where a^2 overflows but k^2 usually doesn't.
+ * With MPFR r10337 and gcc -fsanitize=undefined -fno-sanitize-recover,
+ * this triggers the following error on a 64-bit machine:
+ * /usr/local/gmp-6.0.0-debug/include/gmp.h:2142:3:
+ * runtime error: store to null pointer of type 'mp_limb_t'
+ * (mpn_add_1 is called on a null pointer).
+ */
+static void
+near_overflow_tests (void)
+{
+ mpfr_exp_t old_emax;
+ int i;
+
+ old_emax = mpfr_get_emax ();
+
+ for (i = 0; i < 40; i++)
+ {
+ mpfr_exp_t emax;
+ mpfr_t a, k, c, d, z1, z2;
+ mpfr_rnd_t rnd;
+ mpfr_prec_t prec_a;
+ int add = i & 1, inex, inex1, inex2;
+ mpfr_flags_t flags1, flags2;
+
+ /* In most cases, we do the test with the maximum exponent. */
+ emax = i % 8 != 0 ? MPFR_EMAX_MAX : 64 + (randlimb () % 1);
+ set_emax (emax);
+
+ rnd = RND_RAND ();
+ prec_a = 64 + randlimb () % 100;
+
+ mpfr_init2 (a, prec_a);
+ mpfr_urandom (a, RANDS, MPFR_RNDN);
+ mpfr_set_exp (a, emax/2 + 32);
+
+ mpfr_init2 (k, prec_a - 32);
+ mpfr_urandom (k, RANDS, MPFR_RNDN);
+ mpfr_set_exp (k, emax/2);
+
+ mpfr_init2 (c, prec_a + 1);
+ inex = mpfr_add (c, a, k, MPFR_RNDN);
+ MPFR_ASSERTN (inex == 0);
+
+ mpfr_init2 (d, prec_a);
+ inex = mpfr_sub (d, a, k, MPFR_RNDN);
+ MPFR_ASSERTN (inex == 0);
+ if (add)
+ mpfr_neg (d, d, MPFR_RNDN);
+
+ mpfr_clear_flags ();
+ inex1 = mpfr_sqr (z1, k, rnd);
+ flags1 = __gmpfr_flags;
+
+ mpfr_clear_flags ();
+ inex2 = add ?
+ mpfr_fmma (z2, a, a, c, d, rnd) :
+ mpfr_fmms (z2, a, a, c, d, rnd);
+ flags2 = __gmpfr_flags;
+
+ if (! (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
+ mpfr_equal_p (z1, z2)))
+ {
+ printf ("Error in near_overflow_tests for %s",
+ mpfr_print_rnd_mode (rnd));
+ printf ("Expected ");
+ mpfr_dump (z1);
+ printf (" with inex = %d, flags =", inex1);
+ flags_out (flags1);
+ printf ("Got ");
+ mpfr_dump (z2);
+ printf (" with inex = %d, flags =", inex2);
+ flags_out (flags2);
+ exit (1);
+ }
+ }
+
+ set_emax (old_emax);
+}
+
int
main (int argc, char *argv[])
{
@@ -230,6 +307,8 @@ main (int argc, char *argv[])
random_tests ();
zero_tests ();
max_tests ();
+ near_overflow_tests ();
+ /* TODO: near_underflow_tests (); */
tests_end_mpfr ();
return 0;