OLD | NEW |
| (Empty) |
1 /* tprintf.c -- test file for mpfr_printf and mpfr_vprintf | |
2 | |
3 Copyright 2008, 2009 Free Software Foundation, Inc. | |
4 Contributed by the Arenaire and Cacao projects, INRIA. | |
5 | |
6 The GNU MPFR Library is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU Lesser General Public License as published by | |
8 the Free Software Foundation; either version 2.1 of the License, or (at your | |
9 option) any later version. | |
10 | |
11 The GNU MPFR Library is distributed in the hope that it will be useful, but | |
12 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
14 License for more details. | |
15 | |
16 You should have received a copy of the GNU Lesser General Public License | |
17 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to | |
18 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
19 MA 02110-1301, USA. */ | |
20 | |
21 #if defined HAVE_STDARG | |
22 #include <stdarg.h> | |
23 | |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <stddef.h> | |
27 | |
28 #if HAVE_INTTYPES_H | |
29 # include <inttypes.h> /* for intmax_t */ | |
30 #else | |
31 # if HAVE_STDINT_H | |
32 # include <stdint.h> | |
33 # endif | |
34 #endif | |
35 | |
36 #include "mpfr-test.h" | |
37 #define STDOUT_FILENO 1 | |
38 | |
39 #if MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0) | |
40 | |
41 #define QUOTE(X) NAME(X) | |
42 #define NAME(X) #X | |
43 | |
44 /* unlike other tests, we print out errors to stderr because stdout might be | |
45 redirected */ | |
46 #define check_length(num_test, var, value, var_spec) \ | |
47 if ((var) != (value)) \ | |
48 { \ | |
49 fprintf (stderr, "Error in test #%d: mpfr_printf printed %" \ | |
50 QUOTE(var_spec)" characters instead of %d\n", \ | |
51 (num_test), (var), (value)); \ | |
52 exit (1); \ | |
53 } | |
54 | |
55 #define check_length_with_cmp(num_test, var, value, cmp, var_spec) \ | |
56 if (cmp != 0) \ | |
57 { \ | |
58 mpfr_fprintf (stderr, "Error in test #%d, mpfr_printf printed %" \ | |
59 QUOTE(var_spec)" characters instead of %d\n", \ | |
60 (num_test), (var), (value)); \ | |
61 exit (1); \ | |
62 } | |
63 | |
64 /* limit for random precision in random() */ | |
65 const int prec_max_printf = 5000; | |
66 /* boolean: is stdout redirected to a file ? */ | |
67 int stdout_redirect; | |
68 | |
69 static void | |
70 check (char *fmt, mpfr_t x) | |
71 { | |
72 if (mpfr_printf (fmt, x) == -1) | |
73 { | |
74 fprintf (stderr, "Error in mpfr_printf(\"%s\", ...)\n", fmt); | |
75 | |
76 exit (1); | |
77 } | |
78 putchar ('\n'); | |
79 } | |
80 | |
81 static void | |
82 check_vprintf (char *fmt, ...) | |
83 { | |
84 va_list ap; | |
85 | |
86 va_start (ap, fmt); | |
87 if (mpfr_vprintf (fmt, ap) == -1) | |
88 { | |
89 fprintf (stderr, "Error in mpfr_vprintf(\"%s\", ...)\n", fmt); | |
90 | |
91 va_end (ap); | |
92 exit (1); | |
93 } | |
94 putchar ('\n'); | |
95 va_end (ap); | |
96 } | |
97 | |
98 static void | |
99 check_special (void) | |
100 { | |
101 mpfr_t x; | |
102 | |
103 mpfr_init (x); | |
104 | |
105 mpfr_set_inf (x, 1); | |
106 check ("%Ra", x); | |
107 check ("%Rb", x); | |
108 check ("%Re", x); | |
109 check ("%Rf", x); | |
110 check ("%Rg", x); | |
111 check_vprintf ("%Ra", x); | |
112 check_vprintf ("%Rb", x); | |
113 check_vprintf ("%Re", x); | |
114 check_vprintf ("%Rf", x); | |
115 check_vprintf ("%Rg", x); | |
116 | |
117 mpfr_set_inf (x, -1); | |
118 check ("%Ra", x); | |
119 check ("%Rb", x); | |
120 check ("%Re", x); | |
121 check ("%Rf", x); | |
122 check ("%Rg", x); | |
123 check_vprintf ("%Ra", x); | |
124 check_vprintf ("%Rb", x); | |
125 check_vprintf ("%Re", x); | |
126 check_vprintf ("%Rf", x); | |
127 check_vprintf ("%Rg", x); | |
128 | |
129 mpfr_set_nan (x); | |
130 check ("%Ra", x); | |
131 check ("%Rb", x); | |
132 check ("%Re", x); | |
133 check ("%Rf", x); | |
134 check ("%Rg", x); | |
135 check_vprintf ("%Ra", x); | |
136 check_vprintf ("%Rb", x); | |
137 check_vprintf ("%Re", x); | |
138 check_vprintf ("%Rf", x); | |
139 check_vprintf ("%Rg", x); | |
140 | |
141 mpfr_clear (x); | |
142 } | |
143 | |
144 static void | |
145 check_mixed (void) | |
146 { | |
147 int ch = 'a'; | |
148 signed char sch = -1; | |
149 unsigned char uch = 1; | |
150 short sh = -1; | |
151 unsigned short ush = 1; | |
152 int i = -1; | |
153 int j = 1; | |
154 unsigned int ui = 1; | |
155 long lo = -1; | |
156 unsigned long ulo = 1; | |
157 float f = -1.25; | |
158 double d = -1.25; | |
159 long double ld = -1.25; | |
160 | |
161 ptrdiff_t p = 1; | |
162 size_t sz = 1; | |
163 | |
164 mpz_t mpz; | |
165 mpq_t mpq; | |
166 mpf_t mpf; | |
167 mp_rnd_t rnd = GMP_RNDN; | |
168 | |
169 mpfr_t mpfr; | |
170 mpfr_prec_t prec; | |
171 | |
172 mpz_init (mpz); | |
173 mpz_set_ui (mpz, ulo); | |
174 mpq_init (mpq); | |
175 mpq_set_si (mpq, lo, ulo); | |
176 mpf_init (mpf); | |
177 mpf_set_q (mpf, mpq); | |
178 mpfr_init (mpfr); | |
179 mpfr_set_f (mpfr, mpf, GMP_RNDN); | |
180 prec = mpfr_get_prec (mpfr); | |
181 | |
182 check_vprintf ("a. %Ra, b. %u, c. %lx%n", mpfr, ui, ulo, &j); | |
183 check_length (1, j, 22, d); | |
184 check_vprintf ("a. %c, b. %Rb, c. %u, d. %li%ln", i, mpfr, i, lo, &ulo); | |
185 check_length (2, ulo, 36, lu); | |
186 check_vprintf ("a. %hi, b. %*f, c. %Re%hn", ush, 3, f, mpfr, &ush); | |
187 check_length (3, ush, 29, hu); | |
188 check_vprintf ("a. %hi, b. %f, c. %#.2Rf%n", sh, d, mpfr, &i); | |
189 check_length (4, i, 29, d); | |
190 check_vprintf ("a. %R*A, b. %Fe, c. %i%zn", rnd, mpfr, mpf, sz, &sz); | |
191 check_length (5, sz, 34, zu); | |
192 check_vprintf ("a. %Pu, b. %c, c. %RUG, d. %Zi%Zn", prec, ch, mpfr, mpz, &mpz)
; | |
193 check_length_with_cmp (6, mpz, 24, mpz_cmp_ui (mpz, 24), Zi); | |
194 check_vprintf ("%% a. %#.0RNg, b. %Qx%Rn c. %p", mpfr, mpq, &mpfr, &i); | |
195 check_length_with_cmp (7, mpfr, 16, mpfr_cmp_ui (mpfr, 16), Rg); | |
196 | |
197 #ifndef NPRINTF_T | |
198 check_vprintf ("%% a. %RNg, b. %Qx, c. %td%tn", mpfr, mpq, p, &p); | |
199 check_length (8, p, 21, td); | |
200 #endif | |
201 | |
202 #ifndef NPRINTF_L | |
203 check_vprintf ("a. %RA, b. %Lf, c. %QX%zn", mpfr, ld, mpq, &sz); | |
204 check_length (9, sz, 30, zu); | |
205 #endif | |
206 | |
207 #ifndef NPRINTF_HH | |
208 check_vprintf ("a. %hhi, b. %Ra, c. %hhu%hhn", sch, mpfr, uch, &uch); | |
209 check_length (10, uch, 22, hhu); | |
210 #endif | |
211 | |
212 #if defined(HAVE_LONG_LONG) && !defined(NPRINTF_LL) | |
213 { | |
214 long long llo = -1; | |
215 unsigned long long ullo = 1; | |
216 | |
217 check_vprintf ("a. %Re, b. %llx%Qn", mpfr, ullo, &mpq); | |
218 check_length_with_cmp (11, mpq, 16, mpq_cmp_ui (mpq, 16, 1), Qu); | |
219 check_vprintf ("a. %lli, b. %Rf%Fn", llo, mpfr, &mpf); | |
220 check_length_with_cmp (12, mpf, 12, mpf_cmp_ui (mpf, 12), Fg); | |
221 } | |
222 #endif | |
223 | |
224 #if defined(_MPFR_H_HAVE_INTMAX_T) && !defined(NPRINTF_J) | |
225 { | |
226 intmax_t im = -1; | |
227 uintmax_t uim = 1; | |
228 | |
229 check_vprintf ("a. %*RA, b. %ji%Qn", 10, mpfr, im, &mpq); | |
230 check_length_with_cmp (31, mpq, 20, mpq_cmp_ui (mpq, 20, 1), Qu); | |
231 check_vprintf ("a. %.*Re, b. %jx%Fn", 10, mpfr, uim, &mpf); | |
232 check_length_with_cmp (32, mpf, 25, mpf_cmp_ui (mpf, 25), Fg); | |
233 } | |
234 #endif | |
235 | |
236 mpfr_clear (mpfr); | |
237 mpf_clear (mpf); | |
238 mpq_clear (mpq); | |
239 mpz_clear (mpz); | |
240 } | |
241 | |
242 static void | |
243 check_random (int nb_tests) | |
244 { | |
245 int i; | |
246 mpfr_t x; | |
247 mp_rnd_t rnd; | |
248 char flag[] = | |
249 { | |
250 '-', | |
251 '+', | |
252 ' ', | |
253 '#', | |
254 '0', /* no ambiguity: first zeros are flag zero*/ | |
255 '\'' | |
256 }; | |
257 char specifier[] = | |
258 { | |
259 'a', | |
260 'b', | |
261 'e', | |
262 'f', | |
263 'g' | |
264 }; | |
265 mp_exp_t old_emin, old_emax; | |
266 | |
267 old_emin = mpfr_get_emin (); | |
268 old_emax = mpfr_get_emax (); | |
269 | |
270 mpfr_init (x); | |
271 | |
272 for (i = 0; i < nb_tests; ++i) | |
273 { | |
274 int ret; | |
275 int j, jmax; | |
276 int spec, prec; | |
277 #define FMT_SIZE 13 | |
278 char fmt[FMT_SIZE]; /* at most something like "%-+ #0'.*R*f" */ | |
279 char *ptr = fmt; | |
280 | |
281 tests_default_random (x, 256, MPFR_EMIN_MIN, MPFR_EMAX_MAX); | |
282 rnd = (mp_rnd_t) RND_RAND (); | |
283 | |
284 spec = (int) (randlimb () % 5); | |
285 jmax = (spec == 3 || spec == 4) ? 6 : 5; /* ' flag only with %f or %g */ | |
286 /* advantage small precision */ | |
287 prec = (randlimb () % 2) ? 10 : prec_max_printf; | |
288 prec = (int) (randlimb () % prec); | |
289 if (spec == 3 && mpfr_get_exp (x) > prec_max_printf) | |
290 /* change style 'f' to style 'e' when number x is large */ | |
291 --spec; | |
292 | |
293 *ptr++ = '%'; | |
294 for (j = 0; j < jmax; j++) | |
295 { | |
296 if (randlimb () % 3 == 0) | |
297 *ptr++ = flag[j]; | |
298 } | |
299 *ptr++ = '.'; | |
300 *ptr++ = '*'; | |
301 *ptr++ = 'R'; | |
302 *ptr++ = '*'; | |
303 *ptr++ = specifier[spec]; | |
304 *ptr = '\0'; | |
305 MPFR_ASSERTD (ptr - fmt < FMT_SIZE); | |
306 | |
307 mpfr_printf ("mpfr_printf(\"%s\", %d, %s, %Re)\n", fmt, prec, | |
308 mpfr_print_rnd_mode (rnd), x); | |
309 ret = mpfr_printf (fmt, prec, rnd, x); | |
310 if (ret == -1) | |
311 { | |
312 if (spec == 3 | |
313 && (MPFR_GET_EXP (x) > INT_MAX || MPFR_GET_EXP (x) < -INT_MAX)) | |
314 /* normal failure: x is too large to be output with full precision *
/ | |
315 { | |
316 mpfr_printf ("too large !"); | |
317 } | |
318 else | |
319 { | |
320 printf ("Error in mpfr_printf(\"%s\", %d, %s, ...)", | |
321 fmt, prec, mpfr_print_rnd_mode (rnd)); | |
322 | |
323 if (stdout_redirect) | |
324 { | |
325 if ((fflush (stdout) == EOF) || (fclose (stdout) == -1)) | |
326 { | |
327 perror ("check_random"); | |
328 exit (1); | |
329 } | |
330 } | |
331 exit (1); | |
332 } | |
333 } | |
334 putchar ('\n'); | |
335 } | |
336 | |
337 mpfr_set_emin (old_emin); | |
338 mpfr_set_emax (old_emax); | |
339 | |
340 mpfr_clear (x); | |
341 } | |
342 | |
343 int | |
344 main (int argc, char *argv[]) | |
345 { | |
346 int N; | |
347 | |
348 tests_start_mpfr (); | |
349 | |
350 /* with no argument: prints to /dev/null, | |
351 tprintf N: prints N tests to stdout */ | |
352 if (argc == 1) | |
353 { | |
354 N = 1000; | |
355 stdout_redirect = 1; | |
356 if (freopen ("/dev/null", "w", stdout) == NULL) | |
357 { | |
358 /* We failed to open this device, try with a dummy file */ | |
359 if (freopen ("mpfrtest.txt", "w", stdout) == NULL) | |
360 { | |
361 /* Output the error message to stderr since it is not | |
362 a message about a wrong result in MPFR. Anyway the | |
363 stdandard output may have changed. */ | |
364 fprintf (stderr, "Can't open /dev/null or a temporary file\n"); | |
365 exit (1); | |
366 } | |
367 } | |
368 } | |
369 else | |
370 { | |
371 stdout_redirect = 0; | |
372 N = atoi (argv[1]); | |
373 } | |
374 | |
375 check_special (); | |
376 check_mixed (); | |
377 check_random (N); | |
378 | |
379 if (stdout_redirect) | |
380 { | |
381 if ((fflush (stdout) == EOF) || (fclose (stdout) == -1)) | |
382 perror ("main"); | |
383 } | |
384 tests_end_mpfr (); | |
385 return 0; | |
386 } | |
387 | |
388 #else /* MPFR_VERSION */ | |
389 | |
390 int | |
391 main (void) | |
392 { | |
393 printf ("Warning! Test disabled for this MPFR version.\n"); | |
394 return 0; | |
395 } | |
396 | |
397 #endif /* MPFR_VERSION */ | |
398 | |
399 #else /* HAVE_STDARG */ | |
400 | |
401 int | |
402 main (void) | |
403 { | |
404 /* We have nothing to test. */ | |
405 return 0; | |
406 } | |
407 | |
408 #endif /* HAVE_STDARG */ | |
OLD | NEW |