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.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 using namespace std;
28 
29 
30 bool option_check_standard = false;
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 
72 void
check_mpz(void)73 check_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 
175 void
check_mpq(void)176 check_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 
256 void
check_mpf(void)257 check_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 
436 int
main(int argc,char * argv[])437 main (int argc, char *argv[])
438 {
439   if (argc > 1 && strcmp (argv[1], "-s") == 0)
440     option_check_standard = true;
441 
442   tests_start ();
443 
444   check_mpz ();
445   check_mpq ();
446   check_mpf ();
447 
448   tests_end ();
449   return 0;
450 }
451