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