Exemple #1
0
Fichier : texp.c Projet : jozip/xcl
/* This bug occurs in mpfr_exp_2 on a Linux-64 machine, r5475. */
static void
bug20080731 (void)
{
    mpfr_exp_t emin;
    mpfr_t x, y1, y2;
    mpfr_prec_t prec = 64;

    emin = mpfr_get_emin ();
    set_emin (MPFR_EMIN_MIN);

    mpfr_init2 (x, 200);
    mpfr_set_str (x, "-2.c5c85fdf473de6af278ece700fcbdabd03cd0cb9ca62d8b62c@7",
                  16, MPFR_RNDN);

    mpfr_init2 (y1, prec);
    mpfr_exp (y1, x, MPFR_RNDU);

    /* Compute the result with a higher internal precision. */
    mpfr_init2 (y2, 300);
    mpfr_exp (y2, x, MPFR_RNDU);
    mpfr_prec_round (y2, prec, MPFR_RNDU);

    if (mpfr_cmp0 (y1, y2) != 0)
    {
        printf ("Error in bug20080731\nExpected ");
        mpfr_out_str (stdout, 16, 0, y2, MPFR_RNDN);
        printf ("\nGot      ");
        mpfr_out_str (stdout, 16, 0, y1, MPFR_RNDN);
        printf ("\n");
        exit (1);
    }

    mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
    set_emin (emin);
}
Exemple #2
0
/* Worst case incorrectly rounded in r5573, found with the bad_cases test */
static void
bad_case1 (void)
{
  mpfr_t x, y, z;

  mpfr_init2 (x, 72);
  mpfr_inits2 (6, y, z, (mpfr_ptr) 0);
  mpfr_set_str (x, "1.08310518720928b30e@-120", 16, MPFR_RNDN);
  mpfr_set_str (z, "f.8@59", 16, MPFR_RNDN);
  /* z = rec_sqrt(x) rounded on 6 bits toward 0, the exact value
     being ~= f.bffffffffffffffffa11@59. */
  mpfr_rec_sqrt (y, x, MPFR_RNDZ);
  if (mpfr_cmp0 (y, z) != 0)
    {
      printf ("Error in bad_case1\nexpected ");
      mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
      printf ("\ngot      ");
      mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
      printf ("\n");
      exit (1);
    }
  mpfr_clears (x, y, z, (mpfr_ptr) 0);
}
Exemple #3
0
Fichier : texp.c Projet : jozip/xcl
static void
underflow_up (int extended_emin)
{
    mpfr_t minpos, x, y, t, t2;
    int precx, precy;
    int inex;
    int rnd;
    int e3;
    int i, j;

    mpfr_init2 (minpos, 2);
    mpfr_set_ui (minpos, 0, MPFR_RNDN);
    mpfr_nextabove (minpos);

    /* Let's test values near the underflow boundary.
     *
     * Minimum representable positive number: minpos = 2^(emin - 1).
     * Let's choose an MPFR number x = log(minpos) + eps, with |eps| small
     * (note: eps cannot be 0, and cannot be a rational number either).
     * Then exp(x) = minpos * exp(eps) ~= minpos * (1 + eps + eps^2).
     * We will compute y = rnd(exp(x)) in some rounding mode, precision p.
     *   1. If eps > 0, then in any rounding mode:
     *        rnd(exp(x)) >= minpos and no underflow.
     *      So, let's take x1 = rndu(log(minpos)) in some precision.
     *   2. If eps < 0, then exp(x) < minpos and the result will be either 0
     *      or minpos. An underflow always occurs in MPFR_RNDZ and MPFR_RNDD,
     *      but not necessarily in MPFR_RNDN and MPFR_RNDU (this is underflow
     *      after rounding in an unbounded exponent range). If -a < eps < -b,
     *        minpos * (1 - a) < exp(x) < minpos * (1 - b + b^2).
     *      - If eps > -2^(-p), no underflow in MPFR_RNDU.
     *      - If eps > -2^(-p-1), no underflow in MPFR_RNDN.
     *      - If eps < - (2^(-p-1) + 2^(-2p-1)), underflow in MPFR_RNDN.
     *      - If eps < - (2^(-p) + 2^(-2p+1)), underflow in MPFR_RNDU.
     *      - In MPFR_RNDN, result is minpos iff exp(eps) > 1/2, i.e.
     *        - log(2) < eps < ...
     *
     * Moreover, since precy < MPFR_EXP_THRESHOLD (to avoid tests that take
     * too much time), mpfr_exp() always selects mpfr_exp_2(); so, we need
     * to test mpfr_exp_3() too. This will be done via the e3 variable:
     *   e3 = 0: mpfr_exp(), thus mpfr_exp_2().
     *   e3 = 1: mpfr_exp_3(), via the exp_3() wrapper.
     * i.e.: inex = e3 ? exp_3 (y, x, rnd) : mpfr_exp (y, x, rnd);
     */

    /* Case eps > 0. In revision 5461 (trunk) on a 64-bit Linux machine:
     *   Incorrect flags in underflow_up, eps > 0, MPFR_RNDN and extended emin
     *   for precx = 96, precy = 16, mpfr_exp_3
     *   Got 9 instead of 8.
     * Note: testing this case in several precisions for x and y introduces
     * some useful random. Indeed, the bug is not always triggered.
     * Fixed in r5469.
     */
    for (precx = 16; precx <= 128; precx += 16)
    {
        mpfr_init2 (x, precx);
        mpfr_log (x, minpos, MPFR_RNDU);
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);

            for (e3 = 0; e3 <= 1; e3++)
            {
                RND_LOOP (rnd)
                {
                    int err = 0;

                    mpfr_clear_flags ();
                    inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd)
                           : mpfr_exp (y, x, (mpfr_rnd_t) rnd);
                    if (__gmpfr_flags != MPFR_FLAGS_INEXACT)
                    {
                        printf ("Incorrect flags in underflow_up, eps > 0, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, %s\n",
                                precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp");
                        printf ("Got %u instead of %u.\n", __gmpfr_flags,
                                (unsigned int) MPFR_FLAGS_INEXACT);
                        err = 1;
                    }
                    if (mpfr_cmp0 (y, minpos) < 0)
                    {
                        printf ("Incorrect result in underflow_up, eps > 0, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, %s\n",
                                precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp");
                        mpfr_dump (y);
                        err = 1;
                    }
                    MPFR_ASSERTN (inex != 0);
                    if (rnd == MPFR_RNDD || rnd == MPFR_RNDZ)
                        MPFR_ASSERTN (inex < 0);
                    if (rnd == MPFR_RNDU)
                        MPFR_ASSERTN (inex > 0);
                    if (err)
                        exit (1);
                }
            }

            mpfr_clear (y);
        }
        mpfr_clear (x);
    }

    /* Case - log(2) < eps < 0 in MPFR_RNDN, starting with small-precision x;
     * only check the result and the ternary value.
     * Previous to r5453 (trunk), on 32-bit and 64-bit machines, this fails
     * for precx = 65 and precy = 16, e.g.:
     *   exp_2.c:264:  assertion failed: ...
     * because mpfr_sub (r, x, r, MPFR_RNDU); yields a null value. This is
     * fixed in r5453 by going to next Ziv's iteration.
     */
    for (precx = sizeof(mpfr_exp_t) * CHAR_BIT + 1; precx <= 81; precx += 8)
    {
        mpfr_init2 (x, precx);
        mpfr_log (x, minpos, MPFR_RNDD);  /* |ulp| <= 1/2 */
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);
            inex = mpfr_exp (y, x, MPFR_RNDN);
            if (inex <= 0 || mpfr_cmp0 (y, minpos) != 0)
            {
                printf ("Error in underflow_up, - log(2) < eps < 0");
                if (extended_emin)
                    printf (" and extended emin");
                printf (" for prec = %d\nExpected ", precy);
                mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN);
                printf (" (minimum positive MPFR number) and inex > 0\nGot ");
                mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
                printf ("\nwith inex = %d\n", inex);
                exit (1);
            }
            mpfr_clear (y);
        }
        mpfr_clear (x);
    }

    /* Cases eps ~ -2^(-p) and eps ~ -2^(-p-1). More precisely,
     *   _ for j = 0, eps > -2^(-(p+i)),
     *   _ for j = 1, eps < - (2^(-(p+i)) + 2^(1-2(p+i))),
     * where i = 0 or 1.
     */
    mpfr_inits2 (2, t, t2, (mpfr_ptr) 0);
    for (precy = 16; precy <= 128; precy += 16)
    {
        mpfr_set_ui_2exp (t, 1, - precy, MPFR_RNDN);         /* 2^(-p) */
        mpfr_set_ui_2exp (t2, 1, 1 - 2 * precy, MPFR_RNDN);  /* 2^(-2p+1) */
        precx = sizeof(mpfr_exp_t) * CHAR_BIT + 2 * precy + 8;
        mpfr_init2 (x, precx);
        mpfr_init2 (y, precy);
        for (i = 0; i <= 1; i++)
        {
            for (j = 0; j <= 1; j++)
            {
                if (j == 0)
                {
                    /* Case eps > -2^(-(p+i)). */
                    mpfr_log (x, minpos, MPFR_RNDU);
                }
                else  /* j == 1 */
                {
                    /* Case eps < - (2^(-(p+i)) + 2^(1-2(p+i))). */
                    mpfr_log (x, minpos, MPFR_RNDD);
                    inex = mpfr_sub (x, x, t2, MPFR_RNDN);
                    MPFR_ASSERTN (inex == 0);
                }
                inex = mpfr_sub (x, x, t, MPFR_RNDN);
                MPFR_ASSERTN (inex == 0);

                RND_LOOP (rnd)
                for (e3 = 0; e3 <= 1; e3++)
                {
                    int err = 0;
                    unsigned int flags;

                    flags = MPFR_FLAGS_INEXACT |
                            (((rnd == MPFR_RNDU || rnd == MPFR_RNDA)
                              && (i == 1 || j == 0)) ||
                             (rnd == MPFR_RNDN && (i == 1 && j == 0)) ?
                             0 : MPFR_FLAGS_UNDERFLOW);
                    mpfr_clear_flags ();
                    inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd)
                           : mpfr_exp (y, x, (mpfr_rnd_t) rnd);
                    if (__gmpfr_flags != flags)
                    {
                        printf ("Incorrect flags in underflow_up, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, ",
                                precx, precy);
                        if (j == 0)
                            printf ("eps >~ -2^(-%d)", precy + i);
                        else
                            printf ("eps <~ - (2^(-%d) + 2^(%d))",
                                    precy + i, 1 - 2 * (precy + i));
                        printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp");
                        printf ("Got %u instead of %u.\n",
                                __gmpfr_flags, flags);
                        err = 1;
                    }
                    if (rnd == MPFR_RNDU || rnd == MPFR_RNDA || rnd == MPFR_RNDN ?
                            mpfr_cmp0 (y, minpos) != 0 : MPFR_NOTZERO (y))
                    {
                        printf ("Incorrect result in underflow_up, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, ",
                                precx, precy);
                        if (j == 0)
                            printf ("eps >~ -2^(-%d)", precy + i);
                        else
                            printf ("eps <~ - (2^(-%d) + 2^(%d))",
                                    precy + i, 1 - 2 * (precy + i));
                        printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp");
                        mpfr_dump (y);
                        err = 1;
                    }
                    if (err)
                        exit (1);
                }  /* for (e3 ...) */
            }  /* for (j ...) */
            mpfr_div_2si (t, t, 1, MPFR_RNDN);
            mpfr_div_2si (t2, t2, 2, MPFR_RNDN);
        }  /* for (i ...) */
        mpfr_clears (x, y, (mpfr_ptr) 0);
    }  /* for (precy ...) */
    mpfr_clears (t, t2, (mpfr_ptr) 0);

    /* Case exp(eps) ~= 1/2, i.e. eps ~= - log(2).
     * We choose x0 and x1 with high enough precision such that:
     *   x0 = rndd(rndd(log(minpos)) - rndu(log(2)))
     *   x1 = rndu(rndu(log(minpos)) - rndd(log(2)))
     * In revision 5507 (trunk) on a 64-bit Linux machine, this fails:
     *   Error in underflow_up, eps >~ - log(2) and extended emin
     *   for precy = 16, mpfr_exp
     *   Expected 1.0@-1152921504606846976 (minimum positive MPFR number),
     *   inex > 0 and flags = 9
     *   Got 0
     *   with inex = -1 and flags = 9
     * due to a double-rounding problem in mpfr_mul_2si when rescaling
     * the result.
     */
    mpfr_inits2 (sizeof(mpfr_exp_t) * CHAR_BIT + 64, x, t, (mpfr_ptr) 0);
    for (i = 0; i <= 1; i++)
    {
        mpfr_log (x, minpos, i ? MPFR_RNDU : MPFR_RNDD);
        mpfr_const_log2 (t, i ? MPFR_RNDD : MPFR_RNDU);
        mpfr_sub (x, x, t, i ? MPFR_RNDU : MPFR_RNDD);
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);
            for (e3 = 0; e3 <= 1; e3++)
            {
                unsigned int flags, uflags =
                    MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;

                mpfr_clear_flags ();
                inex = e3 ? exp_3 (y, x, MPFR_RNDN) : mpfr_exp (y, x, MPFR_RNDN);
                flags = __gmpfr_flags;
                if (flags != uflags ||
                        (i ? (inex <= 0 || mpfr_cmp0 (y, minpos) != 0)
                         : (inex >= 0 || MPFR_NOTZERO (y))))
                {
                    printf ("Error in underflow_up, eps %c~ - log(2)",
                            i ? '>' : '<');
                    if (extended_emin)
                        printf (" and extended emin");
                    printf ("\nfor precy = %d, %s\nExpected ", precy,
                            e3 ? "mpfr_exp_3" : "mpfr_exp");
                    if (i)
                    {
                        mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN);
                        printf (" (minimum positive MPFR number),\ninex >");
                    }
                    else
                    {
                        printf ("+0, inex <");
                    }
                    printf (" 0 and flags = %u\nGot ", uflags);
                    mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
                    printf ("\nwith inex = %d and flags = %u\n", inex, flags);
                    exit (1);
                }
            }
            mpfr_clear (y);
        }
    }
    mpfr_clears (x, t, (mpfr_ptr) 0);

    mpfr_clear (minpos);
}