Home | History | Annotate | Line # | Download | only in tests
tfrac.c revision 1.1.1.1
      1 /* Test file for mpfr_frac.
      2 
      3 Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
      4 Contributed by the Arenaire and Cacao projects, INRIA.
      5 
      6 This file is part of the GNU MPFR Library.
      7 
      8 The GNU MPFR Library is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU Lesser General Public License as published by
     10 the Free Software Foundation; either version 3 of the License, or (at your
     11 option) any later version.
     12 
     13 The GNU MPFR Library is distributed in the hope that it will be useful, but
     14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     16 License for more details.
     17 
     18 You should have received a copy of the GNU Lesser General Public License
     19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     22 
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 
     26 #include "mpfr-test.h"
     27 
     28 #define PIP 70
     29 #define PFP 70
     30 #define PMAX (PIP+2*PFP)
     31 
     32 static void
     33 check0 (mpfr_ptr ip, mpfr_ptr fp, mpfr_prec_t prec, mpfr_rnd_t rnd)
     34 {
     35   mpfr_t sum, tmp, dst, fp2;
     36   int inex1, inex2;
     37 
     38   mpfr_init2 (sum, PMAX);
     39   mpfr_init2 (tmp, PMAX);
     40   mpfr_init2 (dst, prec);
     41   mpfr_init2 (fp2, prec);
     42 
     43   if (MPFR_SIGN (ip) != MPFR_SIGN (fp))
     44     {
     45       printf ("Internal error (1)\n");
     46       exit (1);
     47     }
     48   if (mpfr_add (sum, ip, fp, MPFR_RNDZ))
     49     {
     50       printf ("Wrong inexact flag in mpfr_add\n");
     51       exit (1);
     52     }
     53   if (MPFR_SIGN (sum) != MPFR_SIGN (fp))
     54     {
     55       printf ("Internal error (2)\n");
     56       exit (1);
     57     }
     58 
     59   inex1 = mpfr_frac (dst, sum, rnd);
     60   inex2 = mpfr_set (fp2, fp, rnd);
     61   if (inex1 != inex2)
     62     {
     63       printf ("Wrong inexact flag in mpfr_frac for\n");
     64       mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
     65       printf ("\nGot %d instead of %d\n", inex1, inex2);
     66       exit (1);
     67     }
     68   if (!mpfr_number_p (dst) ||
     69       MPFR_SIGN (dst) != MPFR_SIGN (fp2) ||
     70       mpfr_cmp (dst, fp2))
     71     {
     72       printf ("Error in mpfr_frac (y, x, %s) with\nx = ",
     73               mpfr_print_rnd_mode (rnd));
     74       mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
     75       printf ("\nGot        ");
     76       mpfr_out_str (stdout, 2, 0, dst, MPFR_RNDN);
     77       printf ("\ninstead of ");
     78       mpfr_out_str (stdout, 2, 0, fp2, MPFR_RNDN);
     79       printf ("\n");
     80       exit (1);
     81     }
     82 
     83   if (prec == PMAX)
     84     {
     85       inex1 = mpfr_frac (sum, sum, rnd);
     86       if (inex1)
     87         {
     88           printf ("Wrong inexact flag in mpfr_frac\n");
     89           exit (1);
     90         }
     91       if (!mpfr_number_p (sum) ||
     92           MPFR_SIGN (sum) != MPFR_SIGN (fp) ||
     93           mpfr_cmp (sum, fp))
     94         {
     95           printf ("Error in mpfr_frac (x, x, %s) with\nx = ",
     96                   mpfr_print_rnd_mode (rnd));
     97           mpfr_add (tmp, ip, fp, MPFR_RNDZ);
     98           mpfr_out_str (stdout, 2, 0, tmp, MPFR_RNDN);
     99           printf ("\nGot        ");
    100           mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
    101           printf ("\ninstead of ");
    102           mpfr_out_str (stdout, 2, 0, fp, MPFR_RNDN);
    103           printf ("\n");
    104           exit (1);
    105         }
    106     }
    107 
    108   mpfr_clear (fp2);
    109   mpfr_clear (dst);
    110   mpfr_clear (tmp);
    111   mpfr_clear (sum);
    112 }
    113 
    114 static void
    115 check1 (mpfr_ptr ip, mpfr_ptr fp)
    116 {
    117   int rnd;
    118 
    119   for (rnd = 0; rnd < MPFR_RND_MAX ; rnd++)
    120     {
    121       check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd);
    122       check0 (ip, fp, 70, (mpfr_rnd_t) rnd);
    123       mpfr_neg (fp, fp, MPFR_RNDN);
    124       mpfr_neg (ip, ip, MPFR_RNDN);
    125       check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd);
    126       check0 (ip, fp, 70, (mpfr_rnd_t) rnd);
    127       mpfr_neg (fp, fp, MPFR_RNDN);
    128       mpfr_neg (ip, ip, MPFR_RNDN);
    129     }
    130 }
    131 
    132 static void
    133 special (void)
    134 {
    135   mpfr_t z, t;
    136 
    137   mpfr_init (z);
    138   mpfr_init (t);
    139 
    140   mpfr_set_nan (z);
    141   mpfr_frac (t, z, MPFR_RNDN);
    142   if (!mpfr_nan_p (t))
    143     {
    144       printf ("Error for frac(NaN)\n");
    145       exit (1);
    146     }
    147 
    148   mpfr_set_prec (z, 6);
    149   mpfr_set_prec (t, 3);
    150 
    151   mpfr_set_str_binary (z, "0.101101E3");
    152   mpfr_frac (t, z, MPFR_RNDN);
    153   mpfr_set_str_binary (z, "0.101");
    154   if (mpfr_cmp (t, z))
    155     {
    156       printf ("Error in frac(0.101101E3)\n");
    157       exit (1);
    158     }
    159 
    160   mpfr_set_prec (z, 34);
    161   mpfr_set_prec (t, 26);
    162   mpfr_set_str_binary (z, "0.101101010000010011110011001101E9");
    163   mpfr_frac (t, z, MPFR_RNDN);
    164   mpfr_set_str_binary (z, "0.000010011110011001101");
    165   if (mpfr_cmp (t, z))
    166     {
    167       printf ("Error in frac(0.101101010000010011110011001101E9)\n");
    168       exit (1);
    169     }
    170 
    171   mpfr_clear (z);
    172   mpfr_clear (t);
    173 }
    174 
    175 static void
    176 bug20090918 (void)
    177 {
    178   mpfr_t x, y, z;
    179   mp_limb_t y0;
    180   int inexy, inexz;
    181   int r, i;
    182   char *s[] = { "61680.352935791015625", "61680.999999" };
    183   mpfr_exp_t emin;
    184 
    185   emin = mpfr_get_emin ();
    186   mpfr_init2 (x, 32);
    187   mpfr_init2 (y, 13);
    188 
    189   for (i = 0; i <= 9; i++)
    190     {
    191       mpfr_set_str (x, s[i & 1], 10, MPFR_RNDZ);
    192 
    193       RND_LOOP(r)
    194         {
    195           set_emin ((i >> 1) - 3);
    196           inexy = mpfr_frac (y, x, (mpfr_rnd_t) r);
    197           set_emin (emin);
    198           y0 = MPFR_MANT(y)[0];
    199           while (y0 != 0 && (y0 >> 1) << 1 == y0)
    200             y0 >>= 1;
    201           if (y0 > 0x2000)
    202             {
    203               printf ("Error in bug20090918 (significand has more than"
    204                       " 13 bits), i = %d, %s.\n", i,
    205                       mpfr_print_rnd_mode ((mpfr_rnd_t) r));
    206               exit (1);
    207             }
    208           mpfr_init2 (z, 32);
    209           inexz = mpfr_frac (z, x, MPFR_RNDN);
    210           MPFR_ASSERTN (inexz == 0);  /* exact */
    211           inexz = mpfr_prec_round (z, 13, (mpfr_rnd_t) r);
    212           set_emin ((i >> 1) - 3);
    213           inexz = mpfr_check_range (z, inexz, (mpfr_rnd_t) r);
    214           set_emin (emin);
    215           if (mpfr_cmp0 (y, z) != 0)
    216             {
    217               printf ("Error in bug20090918, i = %d, %s.\n", i,
    218                       mpfr_print_rnd_mode ((mpfr_rnd_t) r));
    219               printf ("Expected ");
    220               mpfr_dump (z);
    221               printf ("Got      ");
    222               mpfr_dump (y);
    223               exit (1);
    224             }
    225           if (! SAME_SIGN (inexy, inexz))
    226             {
    227               printf ("Incorrect ternary value in bug20090918, i = %d, %s.\n",
    228                       i, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
    229               printf ("Expected %d, got %d.\n", inexz, inexy);
    230               exit (1);
    231             }
    232           mpfr_clear (z);
    233         }
    234     }
    235 
    236   mpfr_clear (x);
    237   mpfr_clear (y);
    238 }
    239 
    240 #define TEST_FUNCTION mpfr_frac
    241 #include "tgeneric.c"
    242 
    243 int
    244 main (void)
    245 {
    246   mpfr_t ip, fp;
    247   int ni, nf1, nf2;
    248 
    249   tests_start_mpfr ();
    250 
    251   special ();
    252 
    253   mpfr_init2 (ip, PIP);
    254   mpfr_init2 (fp, PFP);
    255 
    256   for (ni = -1; ni < PIP; ni++)
    257     {
    258       if (ni <= 0)
    259         { /* ni + 1 */
    260           mpfr_set_si (ip, ni, MPFR_RNDN);
    261           mpfr_add_ui (ip, ip, 1, MPFR_RNDN);
    262         }
    263       else
    264         { /* 2^ni + 1 */
    265           mpfr_set_ui (ip, 1, MPFR_RNDN);
    266           mpfr_mul_2ui (ip, ip, ni, MPFR_RNDN);
    267           mpfr_add_ui (ip, ip, 1, MPFR_RNDN);
    268         }
    269 
    270       mpfr_set_ui (fp, 0, MPFR_RNDN);
    271       check1 (ip, fp);
    272 
    273       for (nf1 = 1; nf1 < PFP; nf1++)
    274         {
    275           mpfr_set_ui (fp, 1, MPFR_RNDN);
    276           mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN);
    277           check1 (ip, fp);
    278           nf2 = 1 + (randlimb () % (PFP - 1));
    279           mpfr_set_ui (fp, 1, MPFR_RNDN);
    280           mpfr_div_2ui (fp, fp, nf2, MPFR_RNDN);
    281           mpfr_add_ui (fp, fp, 1, MPFR_RNDN);
    282           mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN);
    283           check1 (ip, fp);
    284         }
    285     }
    286 
    287   mpfr_set_ui (ip, 1, MPFR_RNDN);
    288   mpfr_div_ui (ip, ip, 0, MPFR_RNDN);
    289   mpfr_set_ui (fp, 0, MPFR_RNDN);
    290   check1 (ip, fp);  /* test infinities */
    291 
    292   mpfr_clear (ip);
    293   mpfr_clear (fp);
    294 
    295   bug20090918 ();
    296 
    297   test_generic (2, 1000, 10);
    298 
    299   tests_end_mpfr ();
    300   return 0;
    301 }
    302