github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/cxx/t-istream.cc (about) 1 /* Test istream formatted input. 2 3 Copyright 2001-2004 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library test suite. 6 7 The GNU MP Library test suite is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 3 of the License, 10 or (at your option) any later version. 11 12 The GNU MP Library test suite is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 Public License for more details. 16 17 You should have received a copy of the GNU General Public License along with 18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20 #include <iostream> 21 #include <cstdlib> 22 #include <cstring> 23 24 #include "gmp.h" 25 #include "gmp-impl.h" 26 #include "tests.h" 27 28 using namespace std; 29 30 31 // Under option_check_standard, the various test cases for mpz operator>> 32 // are put through the standard operator>> for long, and likewise mpf 33 // operator>> is put through double. 34 // 35 // In g++ 3.3 this results in some printouts about the final position 36 // indicated for something like ".e123". Our mpf code stops at the "e" 37 // since there's no mantissa digits, but g++ reads the whole thing and only 38 // then decides it's bad. 39 40 bool option_check_standard = false; 41 42 43 // On some versions of g++ 2.96 it's been observed that putback() may leave 44 // tellg() unchanged. We believe this is incorrect and presumably the 45 // result of a bug, since for instance it's ok in g++ 2.95 and g++ 3.3. We 46 // detect the problem at runtime and disable affected checks. 47 48 bool putback_tellg_works = true; 49 50 void 51 check_putback_tellg (void) 52 { 53 istringstream input ("hello"); 54 streampos old_pos, new_pos; 55 char c; 56 57 input.get(c); 58 old_pos = input.tellg(); 59 input.putback(c); 60 new_pos = input.tellg(); 61 62 if (old_pos == new_pos) 63 { 64 cout << "Warning, istringstream has a bug: putback() doesn't update tellg().\n";; 65 cout << "Tests on tellg() will be skipped.\n"; 66 putback_tellg_works = false; 67 } 68 } 69 70 71 #define WRONG(str) \ 72 do { \ 73 cout << str ", data[" << i << "]\n"; \ 74 cout << " input: \"" << data[i].input << "\"\n"; \ 75 cout << " flags: " << hex << input.flags() << dec << "\n"; \ 76 } while (0) 77 78 void 79 check_mpz (void) 80 { 81 static const struct { 82 const char *input; 83 int want_pos; 84 const char *want; 85 ios::fmtflags flags; 86 87 } data[] = { 88 89 { "0", -1, "0", (ios::fmtflags) 0 }, 90 { "123", -1, "123", (ios::fmtflags) 0 }, 91 { "0123", -1, "83", (ios::fmtflags) 0 }, 92 { "0x123", -1, "291", (ios::fmtflags) 0 }, 93 { "-123", -1, "-123", (ios::fmtflags) 0 }, 94 { "-0123", -1, "-83", (ios::fmtflags) 0 }, 95 { "-0x123", -1, "-291", (ios::fmtflags) 0 }, 96 { "+123", -1, "123", (ios::fmtflags) 0 }, 97 { "+0123", -1, "83", (ios::fmtflags) 0 }, 98 { "+0x123", -1, "291", (ios::fmtflags) 0 }, 99 100 { "0", -1, "0", ios::dec }, 101 { "1f", 1, "1", ios::dec }, 102 { "011f", 3, "11", ios::dec }, 103 { "123", -1, "123", ios::dec }, 104 { "-1f", 2, "-1", ios::dec }, 105 { "-011f", 4, "-11", ios::dec }, 106 { "-123", -1, "-123", ios::dec }, 107 { "+1f", 2, "1", ios::dec }, 108 { "+011f", 4, "11", ios::dec }, 109 { "+123", -1, "123", ios::dec }, 110 111 { "0", -1, "0", ios::oct }, 112 { "123", -1, "83", ios::oct }, 113 { "-123", -1, "-83", ios::oct }, 114 { "+123", -1, "83", ios::oct }, 115 116 { "0", -1, "0", ios::hex }, 117 { "123", -1, "291", ios::hex }, 118 { "ff", -1, "255", ios::hex }, 119 { "FF", -1, "255", ios::hex }, 120 { "-123", -1, "-291", ios::hex }, 121 { "-ff", -1, "-255", ios::hex }, 122 { "-FF", -1, "-255", ios::hex }, 123 { "+123", -1, "291", ios::hex }, 124 { "+ff", -1, "255", ios::hex }, 125 { "+FF", -1, "255", ios::hex }, 126 { "ab", -1, "171", ios::hex }, 127 { "cd", -1, "205", ios::hex }, 128 { "ef", -1, "239", ios::hex }, 129 130 { " 123", 0, NULL, (ios::fmtflags) 0 }, // not without skipws 131 { " 123", -1, "123", ios::skipws }, 132 }; 133 134 mpz_t got, want; 135 bool got_ok, want_ok; 136 bool got_eof, want_eof; 137 long got_si, want_si; 138 streampos init_tellg, got_pos, want_pos; 139 140 mpz_init (got); 141 mpz_init (want); 142 143 for (size_t i = 0; i < numberof (data); i++) 144 { 145 size_t input_length = strlen (data[i].input); 146 want_pos = (data[i].want_pos == -1 147 ? input_length : data[i].want_pos); 148 want_eof = (want_pos == streampos(input_length)); 149 150 want_ok = (data[i].want != NULL); 151 152 if (data[i].want != NULL) 153 mpz_set_str_or_abort (want, data[i].want, 0); 154 else 155 mpz_set_ui (want, 0L); 156 157 if (option_check_standard && mpz_fits_slong_p (want)) 158 { 159 istringstream input (data[i].input); 160 input.flags (data[i].flags); 161 init_tellg = input.tellg(); 162 want_si = mpz_get_si (want); 163 164 input >> got_si; 165 got_ok = !input.fail(); 166 got_eof = input.eof(); 167 input.clear(); 168 got_pos = input.tellg() - init_tellg; 169 170 if (got_ok != want_ok) 171 { 172 WRONG ("stdc++ operator>> wrong status, check_mpz"); 173 cout << " want_ok: " << want_ok << "\n"; 174 cout << " got_ok: " << got_ok << "\n"; 175 } 176 if (want_ok && got_si != want_si) 177 { 178 WRONG ("stdc++ operator>> wrong result, check_mpz"); 179 cout << " got_si: " << got_si << "\n"; 180 cout << " want_si: " << want_si << "\n"; 181 } 182 if (want_ok && got_eof != want_eof) 183 { 184 WRONG ("stdc++ operator>> wrong EOF state, check_mpz"); 185 cout << " got_eof: " << got_eof << "\n"; 186 cout << " want_eof: " << want_eof << "\n"; 187 } 188 if (putback_tellg_works && got_pos != want_pos) 189 { 190 WRONG ("stdc++ operator>> wrong position, check_mpz"); 191 cout << " want_pos: " << want_pos << "\n"; 192 cout << " got_pos: " << got_pos << "\n"; 193 } 194 } 195 196 { 197 istringstream input (data[i].input); 198 input.flags (data[i].flags); 199 init_tellg = input.tellg(); 200 201 mpz_set_ui (got, 0xDEAD); 202 input >> got; 203 got_ok = !input.fail(); 204 got_eof = input.eof(); 205 input.clear(); 206 got_pos = input.tellg() - init_tellg; 207 208 if (got_ok != want_ok) 209 { 210 WRONG ("mpz operator>> wrong status"); 211 cout << " want_ok: " << want_ok << "\n"; 212 cout << " got_ok: " << got_ok << "\n"; 213 abort (); 214 } 215 if (want_ok && mpz_cmp (got, want) != 0) 216 { 217 WRONG ("mpz operator>> wrong result"); 218 mpz_trace (" got ", got); 219 mpz_trace (" want", want); 220 abort (); 221 } 222 if (want_ok && got_eof != want_eof) 223 { 224 WRONG ("mpz operator>> wrong EOF state"); 225 cout << " want_eof: " << want_eof << "\n"; 226 cout << " got_eof: " << got_eof << "\n"; 227 abort (); 228 } 229 if (putback_tellg_works && got_pos != want_pos) 230 { 231 WRONG ("mpz operator>> wrong position"); 232 cout << " want_pos: " << want_pos << "\n"; 233 cout << " got_pos: " << got_pos << "\n"; 234 abort (); 235 } 236 } 237 } 238 239 mpz_clear (got); 240 mpz_clear (want); 241 } 242 243 void 244 check_mpq (void) 245 { 246 static const struct { 247 const char *input; 248 int want_pos; 249 const char *want; 250 ios::fmtflags flags; 251 252 } data[] = { 253 254 { "0", -1, "0", (ios::fmtflags) 0 }, 255 { "00", -1, "0", (ios::fmtflags) 0 }, 256 { "0x0", -1, "0", (ios::fmtflags) 0 }, 257 258 { "123/456", -1, "123/456", ios::dec }, 259 { "0123/456", -1, "123/456", ios::dec }, 260 { "123/0456", -1, "123/456", ios::dec }, 261 { "0123/0456", -1, "123/456", ios::dec }, 262 263 { "123/456", -1, "83/302", ios::oct }, 264 { "0123/456", -1, "83/302", ios::oct }, 265 { "123/0456", -1, "83/302", ios::oct }, 266 { "0123/0456", -1, "83/302", ios::oct }, 267 268 { "ab", -1, "171", ios::hex }, 269 { "cd", -1, "205", ios::hex }, 270 { "ef", -1, "239", ios::hex }, 271 272 { "0/0", -1, "0/0", (ios::fmtflags) 0 }, 273 { "5/8", -1, "5/8", (ios::fmtflags) 0 }, 274 { "0x5/0x8", -1, "5/8", (ios::fmtflags) 0 }, 275 276 { "123/456", -1, "123/456", (ios::fmtflags) 0 }, 277 { "123/0456", -1, "123/302", (ios::fmtflags) 0 }, 278 { "123/0x456", -1, "123/1110", (ios::fmtflags) 0 }, 279 { "123/0X456", -1, "123/1110", (ios::fmtflags) 0 }, 280 281 { "0123/123", -1, "83/123", (ios::fmtflags) 0 }, 282 { "0123/0123", -1, "83/83", (ios::fmtflags) 0 }, 283 { "0123/0x123", -1, "83/291", (ios::fmtflags) 0 }, 284 { "0123/0X123", -1, "83/291", (ios::fmtflags) 0 }, 285 286 { "0x123/123", -1, "291/123", (ios::fmtflags) 0 }, 287 { "0X123/0123", -1, "291/83", (ios::fmtflags) 0 }, 288 { "0x123/0x123", -1, "291/291", (ios::fmtflags) 0 }, 289 290 { " 123", 0, NULL, (ios::fmtflags) 0 }, // not without skipws 291 { " 123", -1, "123", ios::skipws }, 292 293 { "123 /456", 3, "123", (ios::fmtflags) 0 }, 294 { "123/ 456", 4, NULL, (ios::fmtflags) 0 }, 295 { "123/" , -1, NULL, (ios::fmtflags) 0 }, 296 { "123 /456", 3, "123", ios::skipws }, 297 { "123/ 456", 4, NULL, ios::skipws }, 298 }; 299 300 mpq_t got, want; 301 bool got_ok, want_ok; 302 bool got_eof, want_eof; 303 long got_si, want_si; 304 streampos init_tellg, got_pos, want_pos; 305 306 mpq_init (got); 307 mpq_init (want); 308 309 for (size_t i = 0; i < numberof (data); i++) 310 { 311 size_t input_length = strlen (data[i].input); 312 want_pos = (data[i].want_pos == -1 313 ? input_length : data[i].want_pos); 314 want_eof = (want_pos == streampos(input_length)); 315 316 want_ok = (data[i].want != NULL); 317 318 if (data[i].want != NULL) 319 mpq_set_str_or_abort (want, data[i].want, 0); 320 else 321 mpq_set_ui (want, 0L, 1L); 322 323 if (option_check_standard 324 && mpz_fits_slong_p (mpq_numref(want)) 325 && mpz_cmp_ui (mpq_denref(want), 1L) == 0 326 && strchr (data[i].input, '/') == NULL) 327 { 328 istringstream input (data[i].input); 329 input.flags (data[i].flags); 330 init_tellg = input.tellg(); 331 want_si = mpz_get_si (mpq_numref(want)); 332 333 input >> got_si; 334 got_ok = !input.fail(); 335 got_eof = input.eof(); 336 input.clear(); 337 got_pos = input.tellg() - init_tellg; 338 339 if (got_ok != want_ok) 340 { 341 WRONG ("stdc++ operator>> wrong status, check_mpq"); 342 cout << " want_ok: " << want_ok << "\n"; 343 cout << " got_ok: " << got_ok << "\n"; 344 } 345 if (want_ok && want_si != got_si) 346 { 347 WRONG ("stdc++ operator>> wrong result, check_mpq"); 348 cout << " got_si: " << got_si << "\n"; 349 cout << " want_si: " << want_si << "\n"; 350 } 351 if (want_ok && got_eof != want_eof) 352 { 353 WRONG ("stdc++ operator>> wrong EOF state, check_mpq"); 354 cout << " got_eof: " << got_eof << "\n"; 355 cout << " want_eof: " << want_eof << "\n"; 356 } 357 if (putback_tellg_works && got_pos != want_pos) 358 { 359 WRONG ("stdc++ operator>> wrong position, check_mpq"); 360 cout << " want_pos: " << want_pos << "\n"; 361 cout << " got_pos: " << got_pos << "\n"; 362 } 363 } 364 365 { 366 istringstream input (data[i].input); 367 input.flags (data[i].flags); 368 init_tellg = input.tellg(); 369 mpq_set_si (got, 0xDEAD, 0xBEEF); 370 371 input >> got; 372 got_ok = !input.fail(); 373 got_eof = input.eof(); 374 input.clear(); 375 got_pos = input.tellg() - init_tellg; 376 377 if (got_ok != want_ok) 378 { 379 WRONG ("mpq operator>> wrong status"); 380 cout << " want_ok: " << want_ok << "\n"; 381 cout << " got_ok: " << got_ok << "\n"; 382 abort (); 383 } 384 // don't use mpq_equal, since we allow non-normalized values to be 385 // read, which can trigger ASSERTs in mpq_equal 386 if (want_ok && (mpz_cmp (mpq_numref (got), mpq_numref(want)) != 0 387 || mpz_cmp (mpq_denref (got), mpq_denref(want)) != 0)) 388 { 389 WRONG ("mpq operator>> wrong result"); 390 mpq_trace (" got ", got); 391 mpq_trace (" want", want); 392 abort (); 393 } 394 if (want_ok && got_eof != want_eof) 395 { 396 WRONG ("mpq operator>> wrong EOF state"); 397 cout << " want_eof: " << want_eof << "\n"; 398 cout << " got_eof: " << got_eof << "\n"; 399 abort (); 400 } 401 if (putback_tellg_works && got_pos != want_pos) 402 { 403 WRONG ("mpq operator>> wrong position"); 404 cout << " want_pos: " << want_pos << "\n"; 405 cout << " got_pos: " << got_pos << "\n"; 406 abort (); 407 } 408 } 409 } 410 411 mpq_clear (got); 412 mpq_clear (want); 413 } 414 415 416 void 417 check_mpf (void) 418 { 419 static const struct { 420 const char *input; 421 int want_pos; 422 const char *want; 423 ios::fmtflags flags; 424 425 } data[] = { 426 427 { "0", -1, "0", (ios::fmtflags) 0 }, 428 { "+0", -1, "0", (ios::fmtflags) 0 }, 429 { "-0", -1, "0", (ios::fmtflags) 0 }, 430 { "0.0", -1, "0", (ios::fmtflags) 0 }, 431 { "0.", -1, "0", (ios::fmtflags) 0 }, 432 { ".0", -1, "0", (ios::fmtflags) 0 }, 433 { "+.0", -1, "0", (ios::fmtflags) 0 }, 434 { "-.0", -1, "0", (ios::fmtflags) 0 }, 435 { "+0.00", -1, "0", (ios::fmtflags) 0 }, 436 { "-0.000", -1, "0", (ios::fmtflags) 0 }, 437 { "+0.00", -1, "0", (ios::fmtflags) 0 }, 438 { "-0.000", -1, "0", (ios::fmtflags) 0 }, 439 { "0.0e0", -1, "0", (ios::fmtflags) 0 }, 440 { "0.e0", -1, "0", (ios::fmtflags) 0 }, 441 { ".0e0", -1, "0", (ios::fmtflags) 0 }, 442 { "0.0e-0", -1, "0", (ios::fmtflags) 0 }, 443 { "0.e-0", -1, "0", (ios::fmtflags) 0 }, 444 { ".0e-0", -1, "0", (ios::fmtflags) 0 }, 445 { "0.0e+0", -1, "0", (ios::fmtflags) 0 }, 446 { "0.e+0", -1, "0", (ios::fmtflags) 0 }, 447 { ".0e+0", -1, "0", (ios::fmtflags) 0 }, 448 449 { "1", -1, "1", (ios::fmtflags) 0 }, 450 { "+1", -1, "1", (ios::fmtflags) 0 }, 451 { "-1", -1, "-1", (ios::fmtflags) 0 }, 452 453 { " 0", 0, NULL, (ios::fmtflags) 0 }, // not without skipws 454 { " 0", -1, "0", ios::skipws }, 455 { " +0", -1, "0", ios::skipws }, 456 { " -0", -1, "0", ios::skipws }, 457 458 { "+-123", 1, NULL, (ios::fmtflags) 0 }, 459 { "-+123", 1, NULL, (ios::fmtflags) 0 }, 460 { "1e+-123", 3, NULL, (ios::fmtflags) 0 }, 461 { "1e-+123", 3, NULL, (ios::fmtflags) 0 }, 462 463 { "e123", 0, NULL, (ios::fmtflags) 0 }, // at least one mantissa digit 464 { ".e123", 1, NULL, (ios::fmtflags) 0 }, 465 { "+.e123", 2, NULL, (ios::fmtflags) 0 }, 466 { "-.e123", 2, NULL, (ios::fmtflags) 0 }, 467 468 { "123e", 4, NULL, (ios::fmtflags) 0 }, // at least one exponent digit 469 { "123e-", 5, NULL, (ios::fmtflags) 0 }, 470 { "123e+", 5, NULL, (ios::fmtflags) 0 }, 471 }; 472 473 mpf_t got, want; 474 bool got_ok, want_ok; 475 bool got_eof, want_eof; 476 double got_d, want_d; 477 streampos init_tellg, got_pos, want_pos; 478 479 mpf_init (got); 480 mpf_init (want); 481 482 for (size_t i = 0; i < numberof (data); i++) 483 { 484 size_t input_length = strlen (data[i].input); 485 want_pos = (data[i].want_pos == -1 486 ? input_length : data[i].want_pos); 487 want_eof = (want_pos == streampos(input_length)); 488 489 want_ok = (data[i].want != NULL); 490 491 if (data[i].want != NULL) 492 mpf_set_str_or_abort (want, data[i].want, 0); 493 else 494 mpf_set_ui (want, 0L); 495 496 want_d = mpf_get_d (want); 497 if (option_check_standard && mpf_cmp_d (want, want_d) == 0) 498 { 499 istringstream input (data[i].input); 500 input.flags (data[i].flags); 501 init_tellg = input.tellg(); 502 503 input >> got_d; 504 got_ok = !input.fail(); 505 got_eof = input.eof(); 506 input.clear(); 507 got_pos = input.tellg() - init_tellg; 508 509 if (got_ok != want_ok) 510 { 511 WRONG ("stdc++ operator>> wrong status, check_mpf"); 512 cout << " want_ok: " << want_ok << "\n"; 513 cout << " got_ok: " << got_ok << "\n"; 514 } 515 if (want_ok && want_d != got_d) 516 { 517 WRONG ("stdc++ operator>> wrong result, check_mpf"); 518 cout << " got: " << got_d << "\n"; 519 cout << " want: " << want_d << "\n"; 520 } 521 if (want_ok && got_eof != want_eof) 522 { 523 WRONG ("stdc++ operator>> wrong EOF state, check_mpf"); 524 cout << " got_eof: " << got_eof << "\n"; 525 cout << " want_eof: " << want_eof << "\n"; 526 } 527 if (putback_tellg_works && got_pos != want_pos) 528 { 529 WRONG ("stdc++ operator>> wrong position, check_mpf"); 530 cout << " want_pos: " << want_pos << "\n"; 531 cout << " got_pos: " << got_pos << "\n"; 532 } 533 } 534 535 { 536 istringstream input (data[i].input); 537 input.flags (data[i].flags); 538 init_tellg = input.tellg(); 539 540 mpf_set_ui (got, 0xDEAD); 541 input >> got; 542 got_ok = !input.fail(); 543 got_eof = input.eof(); 544 input.clear(); 545 got_pos = input.tellg() - init_tellg; 546 547 if (got_ok != want_ok) 548 { 549 WRONG ("mpf operator>> wrong status"); 550 cout << " want_ok: " << want_ok << "\n"; 551 cout << " got_ok: " << got_ok << "\n"; 552 abort (); 553 } 554 if (want_ok && mpf_cmp (got, want) != 0) 555 { 556 WRONG ("mpf operator>> wrong result"); 557 mpf_trace (" got ", got); 558 mpf_trace (" want", want); 559 abort (); 560 } 561 if (want_ok && got_eof != want_eof) 562 { 563 WRONG ("mpf operator>> wrong EOF state"); 564 cout << " want_eof: " << want_eof << "\n"; 565 cout << " got_eof: " << got_eof << "\n"; 566 abort (); 567 } 568 if (putback_tellg_works && got_pos != want_pos) 569 { 570 WRONG ("mpf operator>> wrong position"); 571 cout << " want_pos: " << want_pos << "\n"; 572 cout << " got_pos: " << got_pos << "\n"; 573 abort (); 574 } 575 } 576 } 577 578 mpf_clear (got); 579 mpf_clear (want); 580 } 581 582 583 584 int 585 main (int argc, char *argv[]) 586 { 587 if (argc > 1 && strcmp (argv[1], "-s") == 0) 588 option_check_standard = true; 589 590 tests_start (); 591 592 check_putback_tellg (); 593 check_mpz (); 594 check_mpq (); 595 check_mpf (); 596 597 tests_end (); 598 return 0; 599 }