/* Test file for mpfr_frac. Copyright 2002-2014 Free Software Foundation, Inc. Contributed by the AriC and Caramel projects, INRIA. This file is part of the GNU MPFR Library. The GNU MPFR Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The GNU MPFR Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mpfr-test.h" #define PIP 70 #define PFP 70 #define PMAX (PIP+2*PFP) static void check0 (mpfr_ptr ip, mpfr_ptr fp, mpfr_prec_t prec, mpfr_rnd_t rnd) { mpfr_t sum, tmp, dst, fp2; int inex1, inex2; mpfr_init2 (sum, PMAX); mpfr_init2 (tmp, PMAX); mpfr_init2 (dst, prec); mpfr_init2 (fp2, prec); if (MPFR_SIGN (ip) != MPFR_SIGN (fp)) { printf ("Internal error (1)\n"); exit (1); } if (mpfr_add (sum, ip, fp, MPFR_RNDZ)) { printf ("Wrong inexact flag in mpfr_add\n"); exit (1); } if (MPFR_SIGN (sum) != MPFR_SIGN (fp)) { printf ("Internal error (2)\n"); exit (1); } inex1 = mpfr_frac (dst, sum, rnd); inex2 = mpfr_set (fp2, fp, rnd); if (inex1 != inex2) { printf ("Wrong inexact flag in mpfr_frac for\n"); mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); printf ("\nGot %d instead of %d\n", inex1, inex2); exit (1); } if (!mpfr_number_p (dst) || MPFR_SIGN (dst) != MPFR_SIGN (fp2) || mpfr_cmp (dst, fp2)) { printf ("Error in mpfr_frac (y, x, %s) with\nx = ", mpfr_print_rnd_mode (rnd)); mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, dst, MPFR_RNDN); printf ("\ninstead of "); mpfr_out_str (stdout, 2, 0, fp2, MPFR_RNDN); printf ("\n"); exit (1); } if (prec == PMAX) { inex1 = mpfr_frac (sum, sum, rnd); if (inex1) { printf ("Wrong inexact flag in mpfr_frac\n"); exit (1); } if (!mpfr_number_p (sum) || MPFR_SIGN (sum) != MPFR_SIGN (fp) || mpfr_cmp (sum, fp)) { printf ("Error in mpfr_frac (x, x, %s) with\nx = ", mpfr_print_rnd_mode (rnd)); mpfr_add (tmp, ip, fp, MPFR_RNDZ); mpfr_out_str (stdout, 2, 0, tmp, MPFR_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); printf ("\ninstead of "); mpfr_out_str (stdout, 2, 0, fp, MPFR_RNDN); printf ("\n"); exit (1); } } mpfr_clear (fp2); mpfr_clear (dst); mpfr_clear (tmp); mpfr_clear (sum); } static void check1 (mpfr_ptr ip, mpfr_ptr fp) { int rnd; for (rnd = 0; rnd < MPFR_RND_MAX ; rnd++) { check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd); check0 (ip, fp, 70, (mpfr_rnd_t) rnd); mpfr_neg (fp, fp, MPFR_RNDN); mpfr_neg (ip, ip, MPFR_RNDN); check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd); check0 (ip, fp, 70, (mpfr_rnd_t) rnd); mpfr_neg (fp, fp, MPFR_RNDN); mpfr_neg (ip, ip, MPFR_RNDN); } } static void special (void) { mpfr_t z, t; mpfr_init (z); mpfr_init (t); mpfr_set_nan (z); mpfr_frac (t, z, MPFR_RNDN); if (!mpfr_nan_p (t)) { printf ("Error for frac(NaN)\n"); exit (1); } mpfr_set_prec (z, 6); mpfr_set_prec (t, 3); mpfr_set_str_binary (z, "0.101101E3"); mpfr_frac (t, z, MPFR_RNDN); mpfr_set_str_binary (z, "0.101"); if (mpfr_cmp (t, z)) { printf ("Error in frac(0.101101E3)\n"); exit (1); } mpfr_set_prec (z, 34); mpfr_set_prec (t, 26); mpfr_set_str_binary (z, "0.101101010000010011110011001101E9"); mpfr_frac (t, z, MPFR_RNDN); mpfr_set_str_binary (z, "0.000010011110011001101"); if (mpfr_cmp (t, z)) { printf ("Error in frac(0.101101010000010011110011001101E9)\n"); exit (1); } mpfr_clear (z); mpfr_clear (t); } static void bug20090918 (void) { mpfr_t x, y, z; mp_limb_t y0; int inexy, inexz; int r, i; const char *s[] = { "61680.352935791015625", "61680.999999" }; mpfr_exp_t emin; emin = mpfr_get_emin (); mpfr_init2 (x, 32); mpfr_init2 (y, 13); for (i = 0; i <= 9; i++) { mpfr_set_str (x, s[i & 1], 10, MPFR_RNDZ); RND_LOOP(r) { set_emin ((i >> 1) - 3); inexy = mpfr_frac (y, x, (mpfr_rnd_t) r); set_emin (emin); y0 = MPFR_MANT(y)[0]; while (y0 != 0 && (y0 >> 1) << 1 == y0) y0 >>= 1; if (y0 > 0x2000) { printf ("Error in bug20090918 (significand has more than" " 13 bits), i = %d, %s.\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); exit (1); } mpfr_init2 (z, 32); inexz = mpfr_frac (z, x, MPFR_RNDN); MPFR_ASSERTN (inexz == 0); /* exact */ inexz = mpfr_prec_round (z, 13, (mpfr_rnd_t) r); set_emin ((i >> 1) - 3); inexz = mpfr_check_range (z, inexz, (mpfr_rnd_t) r); set_emin (emin); if (mpfr_cmp0 (y, z) != 0) { printf ("Error in bug20090918, i = %d, %s.\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); printf ("Expected "); mpfr_dump (z); printf ("Got "); mpfr_dump (y); exit (1); } if (! SAME_SIGN (inexy, inexz)) { printf ("Incorrect ternary value in bug20090918, i = %d, %s.\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); printf ("Expected %d, got %d.\n", inexz, inexy); exit (1); } mpfr_clear (z); } } mpfr_clear (x); mpfr_clear (y); } #define TEST_FUNCTION mpfr_frac #include "tgeneric.c" int main (void) { mpfr_t ip, fp; int ni, nf1, nf2; tests_start_mpfr (); special (); mpfr_init2 (ip, PIP); mpfr_init2 (fp, PFP); for (ni = -1; ni < PIP; ni++) { if (ni <= 0) { /* ni + 1 */ mpfr_set_si (ip, ni, MPFR_RNDN); mpfr_add_ui (ip, ip, 1, MPFR_RNDN); } else { /* 2^ni + 1 */ mpfr_set_ui (ip, 1, MPFR_RNDN); mpfr_mul_2ui (ip, ip, ni, MPFR_RNDN); mpfr_add_ui (ip, ip, 1, MPFR_RNDN); } mpfr_set_ui (fp, 0, MPFR_RNDN); check1 (ip, fp); for (nf1 = 1; nf1 < PFP; nf1++) { mpfr_set_ui (fp, 1, MPFR_RNDN); mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN); check1 (ip, fp); nf2 = 1 + (randlimb () % (PFP - 1)); mpfr_set_ui (fp, 1, MPFR_RNDN); mpfr_div_2ui (fp, fp, nf2, MPFR_RNDN); mpfr_add_ui (fp, fp, 1, MPFR_RNDN); mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN); check1 (ip, fp); } } mpfr_set_ui (ip, 1, MPFR_RNDN); mpfr_div_ui (ip, ip, 0, MPFR_RNDN); mpfr_set_ui (fp, 0, MPFR_RNDN); check1 (ip, fp); /* test infinities */ mpfr_clear (ip); mpfr_clear (fp); bug20090918 (); test_generic (2, 1000, 10); tests_end_mpfr (); return 0; }