| 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 |