1/* Test ostream formatted output. 2 3Copyright 2001, 2002 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20#include <iostream> 21#include <cstdlib> 22 23#include "gmp.h" 24#include "gmp-impl.h" 25#include "tests.h" 26 27using namespace std; 28 29 30int option_check_standard = 0; 31 32 33#define CALL(expr) \ 34 do { \ 35 got.flags (data[i].flags); \ 36 got.width (data[i].width); \ 37 got.precision (data[i].precision); \ 38 if (data[i].fill == '\0') \ 39 got.fill (' '); \ 40 else \ 41 got.fill (data[i].fill); \ 42 \ 43 if (! (expr)) \ 44 { \ 45 cout << "\"got\" output error\n"; \ 46 abort (); \ 47 } \ 48 if (got.width() != 0) \ 49 { \ 50 cout << "\"got\" width not reset to 0\n"; \ 51 abort (); \ 52 } \ 53 \ 54 } while (0) 55 56 57#define DUMP() \ 58 do { \ 59 cout << " want: |" << data[i].want << "|\n"; \ 60 cout << " got: |" << got.str() << "|\n"; \ 61 cout << " width: " << data[i].width << "\n"; \ 62 cout << " prec: " << got.precision() << "\n"; \ 63 cout << " flags: " << hex << (unsigned long) got.flags() << "\n"; \ 64 } while (0) 65 66#define ABORT() \ 67 do { \ 68 DUMP (); \ 69 abort (); \ 70 } while (0) 71 72void 73check_mpz (void) 74{ 75 static const struct { 76 const char *z; 77 const char *want; 78 ios::fmtflags flags; 79 int width; 80 int precision; 81 char fill; 82 83 } data[] = { 84 85 { "0", "0", ios::dec }, 86 87 { "0", "0", ios::oct }, 88 { "0", "0", ios::oct | ios::showbase }, 89 90 { "0", "0", ios::hex }, 91 { "0", "0x0", ios::hex | ios::showbase }, 92 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase }, 93 94 { "1", "****1", ios::dec, 5, 0, '*' }, 95 96 { "-1", " -1", ios::dec | ios::right, 5 }, 97 { "-1", "- 1", ios::dec | ios::internal, 5 }, 98 { "-1", "-1 ", ios::dec | ios::left, 5 }, 99 100 { "1", " 0x1", ios::hex | ios::showbase | ios::right, 6 }, 101 { "1", "0x 1", ios::hex | ios::showbase | ios::internal, 6 }, 102 { "1", "0x1 ", ios::hex | ios::showbase | ios::left, 6 }, 103 104 { "1", " +0x1", ios::hex | ios::showbase | ios::showpos | ios::right, 105 7 }, 106 { "1", "+0x 1", ios::hex | ios::showbase | ios::showpos | ios::internal, 107 7 }, 108 { "1", "+0x1 ", ios::hex | ios::showbase | ios::showpos | ios::left, 109 7 }, 110 111 { "123", "7b", ios::hex }, 112 { "123", "7B", ios::hex | ios::uppercase }, 113 { "123", "0x7b", ios::hex | ios::showbase }, 114 { "123", "0X7B", ios::hex | ios::showbase | ios::uppercase }, 115 { "-123", "-0x7b", ios::hex | ios::showbase }, 116 { "-123", "-0X7B", ios::hex | ios::showbase | ios::uppercase }, 117 118 { "123", "173", ios::oct }, 119 { "123", "173", ios::oct | ios::uppercase }, 120 { "123", "0173", ios::oct | ios::showbase }, 121 { "123", "0173", ios::oct | ios::showbase | ios::uppercase }, 122 { "-123", "-0173", ios::oct | ios::showbase }, 123 { "-123", "-0173", ios::oct | ios::showbase | ios::uppercase }, 124 125 }; 126 127 size_t i; 128 mpz_t z; 129 130 mpz_init (z); 131 132 for (i = 0; i < numberof (data); i++) 133 { 134 mpz_set_str_or_abort (z, data[i].z, 0); 135 136 if (option_check_standard 137 && mpz_fits_slong_p (z) 138 139 // no negatives or showpos in hex or oct 140 && (((data[i].flags & ios::basefield) == ios::hex 141 || (data[i].flags & ios::basefield) == ios::oct) 142 ? (mpz_sgn (z) >= 0 143 && ! (data[i].flags & ios::showpos)) 144 : 1) 145 ) 146 { 147 ostringstream got; 148 long n = mpz_get_si (z); 149 CALL (got << n); 150 if (got.str().compare (data[i].want) != 0) 151 { 152 cout << "check_mpz data[" << i 153 << "] doesn't match standard ostream output\n"; 154 cout << " z: " << data[i].z << "\n"; 155 cout << " n: " << n << "\n"; 156 DUMP (); 157 } 158 } 159 160 { 161 ostringstream got; 162 CALL (got << z); 163 if (got.str().compare (data[i].want) != 0) 164 { 165 cout << "mpz operator<< wrong, data[" << i << "]\n"; 166 cout << " z: " << data[i].z << "\n"; 167 ABORT (); 168 } 169 } 170 } 171 172 mpz_clear (z); 173} 174 175void 176check_mpq (void) 177{ 178 static const struct { 179 const char *q; 180 const char *want; 181 ios::fmtflags flags; 182 int width; 183 int precision; 184 char fill; 185 186 } data[] = { 187 188 { "0", "0", ios::dec }, 189 { "0", "0", ios::hex }, 190 { "0", "0x0", ios::hex | ios::showbase }, 191 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase }, 192 193 { "5/8", "5/8", ios::dec }, 194 { "5/8", "0X5/0X8", ios::hex | ios::showbase | ios::uppercase }, 195 196 // zero denominator with showbase 197 { "0/0", " 0/0", ios::oct | ios::showbase, 10 }, 198 { "0/0", " 0/0", ios::dec | ios::showbase, 10 }, 199 { "0/0", " 0x0/0x0", ios::hex | ios::showbase, 10 }, 200 { "123/0", " 0173/0", ios::oct | ios::showbase, 10 }, 201 { "123/0", " 123/0", ios::dec | ios::showbase, 10 }, 202 { "123/0", " 0x7b/0x0", ios::hex | ios::showbase, 10 }, 203 { "123/0", " 0X7B/0X0", ios::hex | ios::showbase | ios::uppercase, 10 }, 204 { "0/123", " 0/0173", ios::oct | ios::showbase, 10 }, 205 { "0/123", " 0/123", ios::dec | ios::showbase, 10 }, 206 { "0/123", " 0x0/0x7b", ios::hex | ios::showbase, 10 }, 207 { "0/123", " 0X0/0X7B", ios::hex | ios::showbase | ios::uppercase, 10 }, 208 }; 209 210 size_t i; 211 mpq_t q; 212 213 mpq_init (q); 214 215#define mpq_integer_p(q) (mpz_cmp_ui (mpq_denref(q), 1L) == 0) 216 217 for (i = 0; i < numberof (data); i++) 218 { 219 mpq_set_str_or_abort (q, data[i].q, 0); 220 MPZ_CHECK_FORMAT (mpq_numref (q)); 221 MPZ_CHECK_FORMAT (mpq_denref (q)); 222 223 if (option_check_standard 224 && mpz_fits_slong_p (mpq_numref(q)) 225 && mpq_integer_p (q)) 226 { 227 ostringstream got; 228 long n = mpz_get_si (mpq_numref(q)); 229 CALL (got << n); 230 if (got.str().compare (data[i].want) != 0) 231 { 232 cout << "check_mpq data[" << i 233 << "] doesn't match standard ostream output\n"; 234 cout << " q: " << data[i].q << "\n"; 235 cout << " n: " << n << "\n"; 236 DUMP (); 237 } 238 } 239 240 { 241 ostringstream got; 242 CALL (got << q); 243 if (got.str().compare (data[i].want) != 0) 244 { 245 cout << "mpq operator<< wrong, data[" << i << "]\n"; 246 cout << " q: " << data[i].q << "\n"; 247 ABORT (); 248 } 249 } 250 } 251 252 mpq_clear (q); 253} 254 255 256void 257check_mpf (void) 258{ 259 static const struct { 260 const char *f; 261 const char *want; 262 ios::fmtflags flags; 263 int width; 264 int precision; 265 char fill; 266 267 } data[] = { 268 269 { "0", "0", ios::dec }, 270 { "0", "+0", ios::dec | ios::showpos }, 271 { "0", "0.00000", ios::dec | ios::showpoint }, 272 { "0", "0", ios::dec | ios::fixed }, 273 { "0", "0.", ios::dec | ios::fixed | ios::showpoint }, 274 { "0", "0.000000e+00", ios::dec | ios::scientific }, 275 { "0", "0.000000e+00", ios::dec | ios::scientific | ios::showpoint }, 276 277 { "0", "0", ios::dec, 0, 4 }, 278 { "0", "0.000", ios::dec | ios::showpoint, 0, 4 }, 279 { "0", "0.0000", ios::dec | ios::fixed, 0, 4 }, 280 { "0", "0.0000", ios::dec | ios::fixed | ios::showpoint, 0, 4 }, 281 { "0", "0.0000e+00", ios::dec | ios::scientific, 0, 4 }, 282 { "0", "0.0000e+00", ios::dec | ios::scientific | ios::showpoint, 0, 4 }, 283 284 { "1", "1", ios::dec }, 285 { "1", "+1", ios::dec | ios::showpos }, 286 { "1", "1.00000", ios::dec | ios::showpoint }, 287 { "1", "1", ios::dec | ios::fixed }, 288 { "1", "1.", ios::dec | ios::fixed | ios::showpoint }, 289 { "1", "1.000000e+00", ios::dec | ios::scientific }, 290 { "1", "1.000000e+00", ios::dec | ios::scientific | ios::showpoint }, 291 292 { "1", "1", ios::dec, 0, 4 }, 293 { "1", "1.000", ios::dec | ios::showpoint, 0, 4 }, 294 { "1", "1.0000", ios::dec | ios::fixed, 0, 4 }, 295 { "1", "1.0000", ios::dec | ios::fixed | ios::showpoint, 0, 4 }, 296 { "1", "1.0000e+00", ios::dec | ios::scientific, 0, 4 }, 297 { "1", "1.0000e+00", ios::dec | ios::scientific | ios::showpoint, 0, 4 }, 298 299 { "-1", "-1", ios::dec | ios::showpos }, 300 301 { "-1", " -1", ios::dec, 4 }, 302 { "-1", "- 1", ios::dec | ios::internal, 4 }, 303 { "-1", "-1 ", ios::dec | ios::left, 4 }, 304 305 { "-1", " -0x1", ios::hex | ios::showbase, 6 }, 306 { "-1", "-0x 1", ios::hex | ios::showbase | ios::internal, 6 }, 307 { "-1", "-0x1 ", ios::hex | ios::showbase | ios::left, 6 }, 308 309 { "1", "*********1", ios::dec, 10, 4, '*' }, 310 { "1234", "******1234", ios::dec, 10, 4, '*' }, 311 { "1234", "*****1234.", ios::dec | ios::showpoint, 10, 4, '*' }, 312 313 { "12345", "1.23e+04", ios::dec, 0, 3 }, 314 315 { "12345", "12345.", ios::dec | ios::fixed | ios::showpoint }, 316 317 { "1.9999999", "2", ios::dec, 0, 1 }, 318 { "1.0009999999", "1.001", ios::dec, 0, 4 }, 319 { "1.0001", "1", ios::dec, 0, 4 }, 320 { "1.0004", "1", ios::dec, 0, 4 }, 321 { "1.000555", "1.001", ios::dec, 0, 4 }, 322 323 { "1.0002", "1.000", ios::dec | ios::fixed, 0, 3 }, 324 { "1.0008", "1.001", ios::dec | ios::fixed, 0, 3 }, 325 326 { "0", "0", ios::hex }, 327 { "0", "0x0", ios::hex | ios::showbase }, 328 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase }, 329 { "123", "7b", ios::hex }, 330 { "123", "0x7b", ios::hex | ios::showbase }, 331 { "123", "0X7B", ios::hex | ios::showbase | ios::uppercase }, 332 333 { "0", "0.000@+00", ios::hex | ios::scientific, 0, 3 }, 334 { "256", "1.000@+02", ios::hex | ios::scientific, 0, 3 }, 335 336 { "123", "7.b@+01", ios::hex | ios::scientific, 0, 1 }, 337 { "123", "7.B@+01", ios::hex | ios::scientific | ios::uppercase, 0, 1 }, 338 { "123", "0x7.b@+01", ios::hex | ios::scientific | ios::showbase, 0, 1 }, 339 { "123", "0X7.B@+01", 340 ios::hex | ios::scientific | ios::showbase | ios::uppercase, 0, 1 }, 341 342 { "1099511627776", "1.0@+10", ios::hex | ios::scientific, 0, 1 }, 343 { "1099511627776", "1.0@+10", 344 ios::hex | ios::scientific | ios::uppercase, 0, 1 }, 345 346 { "0.0625", "1.00@-01", ios::hex | ios::scientific, 0, 2 }, 347 348 { "0", "0", ios::oct }, 349 { "123", "173", ios::oct }, 350 { "123", "0173", ios::oct | ios::showbase }, 351 352 // octal showbase suppressed for 0 353 { "0", "0", ios::oct | ios::showbase }, 354 { ".125", "00.1", ios::oct | ios::showbase, 0, 1 }, 355 { ".015625", "00.01", ios::oct | ios::showbase, 0, 2 }, 356 { ".125", "00.1", ios::fixed | ios::oct | ios::showbase, 0, 1 }, 357 { ".015625", "0.0", ios::fixed | ios::oct | ios::showbase, 0, 1 }, 358 { ".015625", "00.01", ios::fixed | ios::oct | ios::showbase, 0, 2 }, 359 360 { "0.125", "1.000000e-01", ios::oct | ios::scientific }, 361 { "0.125", "+1.000000e-01", ios::oct | ios::scientific | ios::showpos }, 362 { "-0.125", "-1.000000e-01", ios::oct | ios::scientific }, 363 { "-0.125", "-1.000000e-01", ios::oct | ios::scientific | ios::showpos }, 364 365 { "0", "0.000e+00", ios::oct | ios::scientific, 0, 3 }, 366 { "256", "4.000e+02", ios::oct | ios::scientific, 0, 3 }, 367 { "256", "04.000e+02", ios::oct | ios::scientific | ios::showbase, 0, 3 }, 368 { "256", "4.000E+02", ios::oct | ios::scientific | ios::uppercase, 0, 3 }, 369 { "256", "04.000E+02", 370 ios::oct | ios::scientific | ios::showbase | ios::uppercase, 0, 3 }, 371 372 { "16777216", "1.000000e+08", ios::oct | ios::scientific }, 373 { "16777216", "1.000000E+08", 374 ios::oct | ios::scientific | ios::uppercase }, 375 { "16777216", "01.000000e+08", 376 ios::oct | ios::scientific | ios::showbase }, 377 { "16777216", "01.000000E+08", 378 ios::oct | ios::scientific | ios::showbase | ios::uppercase }, 379 { "16777216", "+01.000000e+08", 380 ios::oct | ios::scientific | ios::showbase | ios::showpos }, 381 { "16777216", "+01.000000E+08", ios::oct | ios::scientific 382 | ios::showbase | ios::showpos | ios::uppercase }, 383 { "-16777216", "-01.000000e+08", 384 ios::oct | ios::scientific | ios::showbase | ios::showpos }, 385 { "-16777216", "-01.000000E+08", ios::oct | ios::scientific 386 | ios::showbase | ios::showpos | ios::uppercase }, 387 388 }; 389 390 size_t i; 391 mpf_t f, f2; 392 double d; 393 394 mpf_init (f); 395 mpf_init (f2); 396 397 for (i = 0; i < numberof (data); i++) 398 { 399 mpf_set_str_or_abort (f, data[i].f, 0); 400 401 d = mpf_get_d (f); 402 mpf_set_d (f2, d); 403 if (option_check_standard && mpf_cmp (f, f2) == 0 404 && ! (data[i].flags & (ios::hex | ios::oct | ios::showbase))) 405 { 406 ostringstream got; 407 CALL (got << d); 408 if (got.str().compare (data[i].want) != 0) 409 { 410 cout << "check_mpf data[" << i 411 << "] doesn't match standard ostream output\n"; 412 cout << " f: " << data[i].f << "\n"; 413 cout << " d: " << d << "\n"; 414 DUMP (); 415 } 416 } 417 418 { 419 ostringstream got; 420 CALL (got << f); 421 if (got.str().compare (data[i].want) != 0) 422 { 423 cout << "mpf operator<< wrong, data[" << i << "]\n"; 424 cout << " f: " << data[i].f << "\n"; 425 ABORT (); 426 } 427 } 428 } 429 430 mpf_clear (f); 431 mpf_clear (f2); 432} 433 434 435 436int 437main (int argc, char *argv[]) 438{ 439 if (argc > 1 && strcmp (argv[1], "-s") == 0) 440 option_check_standard = 1; 441 442 tests_start (); 443 444 check_mpz (); 445 check_mpq (); 446 check_mpf (); 447 448 tests_end (); 449 return 0; 450} 451