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
check_mpz(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
check_mpq(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
check_mpf(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
main(int argc,char * argv[])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 }
450