tfrac.c revision 1.1.1.1
1/* Test file for mpfr_frac.
2
3Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4Contributed by the Arenaire and Cacao projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 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
32static void
33check0 (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
114static void
115check1 (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
132static void
133special (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
175static void
176bug20090918 (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
243int
244main (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