xref: /openbsd-src/gnu/lib/libstdc++/libstdc++/testsuite/27_io/ostream_inserter_arith.cc (revision 67b993f490445e9d86721b8e600ae1baf4574be7)
1 // 1999-11-15 Kevin Ediger  <kediger@licor.com>
2 // test the floating point inserters (facet num_put)
3 
4 // Copyright (C) 1999, 2002 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 // USA.
21 
22 #include <cstdio> // for sprintf
23 #include <cmath> // for abs
24 #include <cfloat> // for DBL_EPSILON
25 #include <iostream>
26 #include <iomanip>
27 #include <locale>
28 #include <sstream>
29 #include <limits>
30 #include <testsuite_hooks.h>
31 
32 using namespace std;
33 
34 #ifndef DEBUG_ASSERT
35 #  define TEST_NUMPUT_VERBOSE 1
36 #endif
37 
38 struct _TestCase
39 {
40   double val;
41 
42   int precision;
43   int width;
44   char decimal;
45   char fill;
46 
47   bool fixed;
48   bool scientific;
49   bool showpos;
50   bool showpoint;
51   bool uppercase;
52   bool internal;
53   bool left;
54   bool right;
55 
56   const char* result;
57 #if defined(_GLIBCPP_USE_WCHAR_T)
58   const wchar_t* wresult;
59 #endif
60 };
61 
62 static bool T=true;
63 static bool F=false;
64 
65 static _TestCase testcases[] =
66 {
67 #if defined(_GLIBCPP_USE_WCHAR_T)
68   // standard output (no formatting applied) 1-4
69   { 1.2, 6,0,'.',' ', F,F,F,F,F,F,F,F, "1.2",L"1.2" },
70   { 54, 6,0,'.',' ', F,F,F,F,F,F,F,F, "54",L"54" },
71   { -.012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-0.012",L"-0.012" },
72   { -.00000012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-1.2e-07",L"-1.2e-07" },
73 
74   // fixed formatting 5-11
75   { 10.2345, 0,0,'.',' ', T,F,F,F,F,F,F,F, "10",L"10" },
76   { 10.2345, 0,0,'.',' ', T,F,F,T,F,F,F,F, "10.",L"10." },
77   { 10.2345, 1,0,'.',' ', T,F,F,F,F,F,F,F, "10.2",L"10.2" },
78   { 10.2345, 4,0,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
79   { 10.2345, 6,0,'.',' ', T,F,T,F,F,F,F,F, "+10.234500",L"+10.234500" },
80   { -10.2345, 6,0,'.',' ', T,F,F,F,F,F,F,F, "-10.234500",L"-10.234500" },
81   { -10.2345, 6,0,',',' ', T,F,F,F,F,F,F,F, "-10,234500",L"-10,234500" },
82 
83   // fixed formatting with width 12-22
84   { 10.2345, 4,5,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
85   { 10.2345, 4,6,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
86   { 10.2345, 4,7,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
87   { 10.2345, 4,8,'.',' ', T,F,F,F,F,F,F,F, " 10.2345",L" 10.2345" },
88   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,F,F, "   10.2345",L"   10.2345" },
89   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,T,F, "10.2345   ",L"10.2345   " },
90   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,F,T, "   10.2345",L"   10.2345" },
91   { 10.2345, 4,10,'.',' ', T,F,F,F,F,T,F,F, "   10.2345",L"   10.2345" },
92   { -10.2345, 4,10,'.',' ', T,F,F,F,F,T,F,F, "-  10.2345",L"-  10.2345" },
93   { -10.2345, 4,10,'.','A', T,F,F,F,F,T,F,F, "-AA10.2345",L"-AA10.2345" },
94   { 10.2345, 4,10,'.','#', T,F,T,F,F,T,F,F, "+##10.2345",L"+##10.2345" },
95 
96   // scientific formatting 23-29
97   { 1.23e+12, 1,0,'.',' ', F,T,F,F,F,F,F,F, "1.2e+12",L"1.2e+12" },
98   { 1.23e+12, 1,0,'.',' ', F,T,F,F,T,F,F,F, "1.2E+12",L"1.2E+12" },
99   { 1.23e+12, 2,0,'.',' ', F,T,F,F,F,F,F,F, "1.23e+12",L"1.23e+12" },
100   { 1.23e+12, 3,0,'.',' ', F,T,F,F,F,F,F,F, "1.230e+12",L"1.230e+12" },
101   { 1.23e+12, 3,0,'.',' ', F,T,T,F,F,F,F,F, "+1.230e+12",L"+1.230e+12" },
102   { -1.23e-12, 3,0,'.',' ', F,T,F,F,F,F,F,F, "-1.230e-12",L"-1.230e-12" },
103   { 1.23e+12, 3,0,',',' ', F,T,F,F,F,F,F,F, "1,230e+12",L"1,230e+12" },
104 #else
105   // standard output (no formatting applied)
106   { 1.2, 6,0,'.',' ', F,F,F,F,F,F,F,F, "1.2" },
107   { 54, 6,0,'.',' ', F,F,F,F,F,F,F,F, "54" },
108   { -.012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-0.012" },
109   { -.00000012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-1.2e-07" },
110 
111   // fixed formatting
112   { 10.2345, 0,0,'.',' ', T,F,F,F,F,F,F,F, "10" },
113   { 10.2345, 0,0,'.',' ', T,F,F,T,F,F,F,F, "10." },
114   { 10.2345, 1,0,'.',' ', T,F,F,F,F,F,F,F, "10.2" },
115   { 10.2345, 4,0,'.',' ', T,F,F,F,F,F,F,F, "10.2345" },
116   { 10.2345, 6,0,'.',' ', T,F,T,F,F,F,F,F, "+10.234500" },
117   { -10.2345, 6,0,'.',' ', T,F,F,F,F,F,F,F, "-10.234500" },
118   { -10.2345, 6,0,',',' ', T,F,F,F,F,F,F,F, "-10,234500" },
119 
120   // fixed formatting with width
121   { 10.2345, 4,5,'.',' ', T,F,F,F,F,F,F,F, "10.2345" },
122   { 10.2345, 4,6,'.',' ', T,F,F,F,F,F,F,F, "10.2345" },
123   { 10.2345, 4,7,'.',' ', T,F,F,F,F,F,F,F, "10.2345" },
124   { 10.2345, 4,8,'.',' ', T,F,F,F,F,F,F,F, " 10.2345" },
125   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,F,F, "   10.2345" },
126   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,T,F, "10.2345   " },
127   { 10.2345, 4,10,'.',' ', T,F,F,F,F,F,F,T, "   10.2345" },
128   { 10.2345, 4,10,'.',' ', T,F,F,F,F,T,F,F, "   10.2345" },
129   { -10.2345, 4,10,'.',' ', T,F,F,F,F,T,F,F, "-  10.2345" },
130   { -10.2345, 4,10,'.','A', T,F,F,F,F,T,F,F, "-AA10.2345" },
131   { 10.2345, 4,10,'.','#', T,F,T,F,F,T,F,F, "+##10.2345" },
132 
133   // scientific formatting
134   { 1.23e+12, 1,0,'.',' ', F,T,F,F,F,F,F,F, "1.2e+12" },
135   { 1.23e+12, 1,0,'.',' ', F,T,F,F,T,F,F,F, "1.2E+12" },
136   { 1.23e+12, 2,0,'.',' ', F,T,F,F,F,F,F,F, "1.23e+12" },
137   { 1.23e+12, 3,0,'.',' ', F,T,F,F,F,F,F,F, "1.230e+12" },
138   { 1.23e+12, 3,0,'.',' ', F,T,T,F,F,F,F,F, "+1.230e+12" },
139   { -1.23e-12, 3,0,'.',' ', F,T,F,F,F,F,F,F, "-1.230e-12" },
140   { 1.23e+12, 3,0,',',' ', F,T,F,F,F,F,F,F, "1,230e+12" },
141 #endif
142 };
143 
144 template<typename _CharT>
145 class testpunct : public numpunct<_CharT>
146 {
147 public:
148   typedef _CharT  char_type;
149   const char_type dchar;
150 
151   explicit
testpunct(char_type decimal_char)152   testpunct(char_type decimal_char) : numpunct<_CharT>(), dchar(decimal_char)
153   { }
154 
155 protected:
156   char_type
do_decimal_point() const157   do_decimal_point() const
158   { return dchar; }
159 
160   char_type
do_thousands_sep() const161   do_thousands_sep() const
162   { return ','; }
163 
164   string
do_grouping() const165   do_grouping() const
166   { return string(); }
167 };
168 
169 template<typename _CharT>
apply_formatting(const _TestCase & tc,basic_ostream<_CharT> & os)170 void apply_formatting(const _TestCase & tc, basic_ostream<_CharT> & os)
171 {
172   os.precision(tc.precision);
173   os.width(tc.width);
174   os.fill(static_cast<_CharT>(tc.fill));
175   if (tc.fixed)
176     os.setf(ios::fixed);
177   if (tc.scientific)
178     os.setf(ios::scientific);
179   if (tc.showpos)
180     os.setf(ios::showpos);
181   if (tc.showpoint)
182     os.setf(ios::showpoint);
183   if (tc.uppercase)
184     os.setf(ios::uppercase);
185   if (tc.internal)
186     os.setf(ios::internal);
187   if (tc.left)
188     os.setf(ios::left);
189   if (tc.right)
190     os.setf(ios::right);
191 }
192 
193 int
test01()194 test01()
195 {
196   bool test = true;
197   for (int j=0; j<sizeof(testcases)/sizeof(testcases[0]); j++)
198     {
199       _TestCase & tc = testcases[j];
200 #ifdef TEST_NUMPUT_VERBOSE
201       cout << "expect: " << tc.result << endl;
202 #endif
203       // test double with char type
204       {
205         testpunct<char>* __tp = new testpunct<char>(tc.decimal);
206         ostringstream os;
207         locale __loc(os.getloc(), __tp);
208         os.imbue(__loc);
209         apply_formatting(tc, os);
210         os << tc.val;
211 #ifdef TEST_NUMPUT_VERBOSE
212         cout << j << "result 1: " << os.str() << endl;
213 #endif
214         VERIFY( os && os.str() == tc.result );
215       }
216       // test long double with char type
217       {
218         testpunct<char>* __tp = new testpunct<char>(tc.decimal);
219         ostringstream os;
220         locale __loc(os.getloc(), __tp);
221         os.imbue(__loc);
222         apply_formatting(tc, os);
223         os << (long double)tc.val;
224 #ifdef TEST_NUMPUT_VERBOSE
225         cout << j << "result 2: " << os.str() << endl;
226 #endif
227         VERIFY( os && os.str() == tc.result );
228       }
229 #if defined(_GLIBCPP_USE_WCHAR_T)
230       // test double with wchar_t type
231       {
232         testpunct<wchar_t>* __tp = new testpunct<wchar_t>(tc.decimal);
233         wostringstream os;
234         locale __loc(os.getloc(), __tp);
235         os.imbue(__loc);
236         apply_formatting(tc, os);
237         os << tc.val;
238         VERIFY( os && os.str() == tc.wresult );
239       }
240       // test long double with wchar_t type
241       {
242         testpunct<wchar_t>* __tp = new testpunct<wchar_t>(tc.decimal);
243         wostringstream os;
244         locale __loc(os.getloc(), __tp);
245         os.imbue(__loc);
246         apply_formatting(tc, os);
247         os << (long double)tc.val;
248         VERIFY( os && os.str() == tc.wresult );
249       }
250 #endif
251     }
252 
253   return 0;
254 }
255 
256 int
test02()257 test02()
258 {
259   bool test = true;
260   // make sure we can output a very long float
261   long double val = 1.2345678901234567890123456789e+1000L;
262   int prec = numeric_limits<long double>::digits10;
263 
264   ostringstream os;
265   os.precision(prec);
266   os.setf(ios::scientific);
267   os << val;
268 
269   char largebuf[512];
270   snprintf(largebuf, 512, "%.*Le", prec, val);
271 #ifdef TEST_NUMPUT_VERBOSE
272   cout << "expect: " << largebuf << endl;
273   cout << "result: " << os.str() << endl;
274 #endif
275   VERIFY(os && os.str() == largebuf);
276 
277   // Make sure we can output a long float in fixed format
278   // without seg-faulting (libstdc++/4402)
279   double val2 = 3.5e230;
280 
281   ostringstream os2;
282   os2.precision(3);
283   os2.setf(ios::fixed);
284   os2 << val2;
285 
286   snprintf(largebuf, 512, "%.*f", 3, val2);
287 #ifdef TEST_NUMPUT_VERBOSE
288   cout << "expect: " << largebuf << endl;
289   cout << "result: " << os2.str() << endl;
290 #endif
291   VERIFY(os2 && os2.str() == largebuf);
292 
293   // Check it can be done in a locale with grouping on.
294   locale loc2("de_DE");
295   os2.imbue(loc2);
296   os2 << fixed << setprecision(3) << val2 << endl;
297   os2 << endl;
298   os2 << fixed << setprecision(1) << val2 << endl;
299 
300   return 0;
301 }
302 
303 template<typename T>
304 bool
test03_check(T n)305 test03_check(T n)
306 {
307   stringbuf strbuf;
308   ostream o(&strbuf);
309   const char *expect;
310   bool test = true;
311 
312   if (numeric_limits<T>::digits + 1 == 16)
313     expect = "177777 ffff";
314   else if (numeric_limits<T>::digits + 1 == 32)
315     expect = "37777777777 ffffffff";
316   else if (numeric_limits<T>::digits + 1 == 64)
317     expect = "1777777777777777777777 ffffffffffffffff";
318   else
319     expect = "wow, you've got some big numbers here";
320 
321   o << oct << n << ' ' << hex << n;
322   VERIFY ( strbuf.str() == expect );
323 
324   return test;
325 }
326 
327 int
test03()328 test03()
329 {
330   short s = -1;
331   int i = -1;
332   long l = -1;
333   bool test = true;
334 
335   test &= test03_check (s);
336   test &= test03_check (i);
337   test &= test03_check (l);
338 
339   return 0;
340 }
341 
342 // libstdc++/3655
343 int
test04()344 test04()
345 {
346   stringbuf strbuf1, strbuf2;
347   ostream o1(&strbuf1), o2(&strbuf2);
348   bool test = true;
349 
350   o1 << hex << showbase << setw(6) << internal << 0xff;
351   VERIFY( strbuf1.str() == "0x  ff" );
352 
353   // ... vs internal-adjusted const char*-type objects
354   o2 << hex << showbase << setw(6) << internal << "0xff";
355   VERIFY( strbuf2.str() == "  0xff" );
356 
357   return 0;
358 }
359 
360 int
test05()361 test05()
362 {
363   bool test = true;
364 
365   double pi = 3.14159265358979323846;
366   ostringstream ostr;
367   ostr.precision(20);
368   ostr << pi;
369   string sval = ostr.str();
370   istringstream istr (sval);
371   double d;
372   istr >> d;
373   VERIFY( abs(pi-d)/pi < DBL_EPSILON );
374   return 0;
375 }
376 
377 
378 // libstdc++/9151
379 int
test06()380 test06()
381 {
382   bool test = true;
383 
384   int prec = numeric_limits<double>::digits10 + 2;
385   double oval = numeric_limits<double>::min();
386 
387   stringstream ostr;
388   ostr.precision(prec);
389   ostr << oval;
390   string sval = ostr.str();
391   istringstream istr (sval);
392   double ival;
393   istr >> ival;
394   VERIFY( abs(oval-ival)/oval < DBL_EPSILON );
395   return 0;
396 }
397 
398 int
main()399 main()
400 {
401   test01();
402   test02();
403   test03();
404   test04();
405   test05();
406   test06();
407 #ifdef TEST_NUMPUT_VERBOSE
408   cout << "Test passed!" << endl;
409 #endif
410   return 0;
411 }
412