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