]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2011 Paul A. Bristow | |
3 | ||
4 | // Distributed under the Boost Software License, Version 1.0. | |
5 | // (See accompanying file LICENSE_1_0.txt | |
6 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | // test_nonfinite_trap.cpp | |
9 | ||
10 | #ifdef _MSC_VER | |
11 | # pragma warning(disable : 4127) // Expression is constant. | |
12 | #endif | |
13 | ||
14 | #define BOOST_TEST_MAIN | |
15 | ||
92f5a8d4 | 16 | #include <boost/test/unit_test.hpp> |
7c673cae FG |
17 | #include <libs/math/test/almost_equal.ipp> // Similar to BOOST_CLOSE_FRACTION. |
18 | #include <libs/math/test/s_.ipp> // To create test strings like std::basic_string<CharType> s = S_("0 -0"); | |
19 | #include <boost/math/special_functions/nonfinite_num_facets.hpp> | |
20 | ||
21 | #include <locale> | |
22 | #include <sstream> | |
23 | #include <iomanip> | |
24 | ||
25 | namespace { | |
26 | ||
27 | // Using an anonymous namespace resolves ambiguities on platforms | |
28 | // with fpclassify etc functions at global scope. | |
29 | ||
30 | using namespace boost::math; | |
31 | using boost::math::signbit; | |
32 | using boost::math::changesign; | |
33 | using (boost::math::isnan)(; | |
34 | ||
35 | //------------------------------------------------------------------------------ | |
36 | // Test nonfinite_num_put and nonfinite_num_get facets by checking | |
37 | // loopback (output and re-input) of a few values, | |
38 | // but using all the built-in char and floating-point types. | |
f67539c2 | 39 | // Only the default output is used but various ostream options are tested separately below. |
7c673cae FG |
40 | // Finite, infinite and NaN values (positive and negative) are used for the test. |
41 | ||
42 | void trap_test_finite(); | |
43 | void trap_test_inf(); | |
44 | void trap_test_nan(); | |
45 | ||
46 | BOOST_AUTO_TEST_CASE(trap_test) | |
47 | { | |
48 | trap_test_finite(); | |
49 | trap_test_inf(); | |
50 | trap_test_nan(); | |
51 | } | |
52 | ||
53 | //------------------------------------------------------------------------------ | |
54 | ||
55 | template<class CharType, class ValType> void trap_test_finite_impl(); | |
56 | ||
57 | void trap_test_finite() | |
58 | { // Test finite using all the built-in char and floating-point types. | |
59 | trap_test_finite_impl<char, float>(); | |
60 | trap_test_finite_impl<char, double>(); | |
61 | trap_test_finite_impl<char, long double>(); | |
62 | trap_test_finite_impl<wchar_t, float>(); | |
63 | trap_test_finite_impl<wchar_t, double>(); | |
64 | trap_test_finite_impl<wchar_t, long double>(); | |
65 | } | |
66 | ||
67 | template<class CharType, class ValType> void trap_test_finite_impl() | |
68 | { | |
69 | std::locale old_locale; | |
70 | std::locale tmp_locale(old_locale, | |
71 | new nonfinite_num_put<CharType>(trap_infinity | trap_nan)); | |
72 | std::locale new_locale(tmp_locale, | |
73 | new nonfinite_num_get<CharType>(trap_infinity | trap_nan)); | |
74 | ||
75 | std::basic_stringstream<CharType> ss; | |
76 | ss.imbue(new_locale); | |
77 | ||
78 | ValType a1 = (ValType)1.2; | |
79 | ValType a2 = (ValType)-3.5; | |
80 | ValType a3 = (std::numeric_limits<ValType>::max)(); | |
81 | ValType a4 = -(std::numeric_limits<ValType>::max)(); | |
82 | ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4; // 1.2, -3.5, max, -max | |
83 | ||
84 | ValType b1, b2, b3, b4; | |
85 | ss >> b1 >> b2 >> b3 >> b4; | |
86 | ||
87 | BOOST_CHECK(almost_equal(b1, a1)); | |
88 | BOOST_CHECK(almost_equal(b2, a2)); | |
89 | BOOST_CHECK(almost_equal(b3, a3)); | |
90 | BOOST_CHECK(almost_equal(b4, a4)); | |
91 | BOOST_CHECK(b3 != std::numeric_limits<ValType>::infinity()); | |
92 | BOOST_CHECK(b4 != -std::numeric_limits<ValType>::infinity()); | |
93 | BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit); | |
94 | ||
95 | ss.clear(); | |
96 | ss.str(S_("")); | |
97 | ||
98 | ss << "++5"; | |
99 | ValType b5; | |
100 | ss >> b5; | |
101 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); | |
102 | } | |
103 | ||
104 | //------------------------------------------------------------------------------ | |
105 | ||
106 | template<class CharType, class ValType> void trap_test_inf_impl(); | |
107 | template<class CharType, class ValType> void trap_test_put_inf_impl(); | |
108 | template<class CharType, class ValType> void trap_test_get_inf_impl(); | |
109 | ||
110 | void trap_test_inf() | |
111 | { // Test infinity using all the built-in char and floating-point types. | |
112 | trap_test_inf_impl<char, float>(); | |
113 | trap_test_inf_impl<char, double>(); | |
114 | trap_test_inf_impl<char, long double>(); | |
115 | trap_test_inf_impl<wchar_t, float>(); | |
116 | trap_test_inf_impl<wchar_t, double>(); | |
117 | trap_test_inf_impl<wchar_t, long double>(); | |
118 | } | |
119 | ||
120 | template<class CharType, class ValType> void trap_test_inf_impl() | |
121 | { | |
122 | trap_test_put_inf_impl<CharType, ValType>(); | |
123 | trap_test_get_inf_impl<CharType, ValType>(); | |
124 | } | |
125 | ||
126 | template<class CharType, class ValType> void trap_test_put_inf_impl() | |
127 | { | |
128 | std::locale old_locale; | |
129 | std::locale new_locale(old_locale, | |
130 | new nonfinite_num_put<CharType>(trap_infinity)); | |
131 | ||
132 | std::basic_stringstream<CharType> ss; | |
133 | ss.imbue(new_locale); | |
134 | ||
135 | ValType a1 = std::numeric_limits<ValType>::infinity(); | |
136 | ss << a1; | |
137 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit | |
138 | || ss.rdstate() == std::ios_base::badbit); | |
139 | ss.clear(); | |
140 | ||
141 | ValType a2 = -std::numeric_limits<ValType>::infinity(); | |
142 | ss << a2; | |
143 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit | |
144 | || ss.rdstate() == std::ios_base::badbit); | |
145 | } | |
146 | ||
147 | template<class CharType, class ValType> void trap_test_get_inf_impl() | |
148 | { | |
149 | std::locale old_locale; | |
150 | std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>); | |
151 | std::locale new_locale(tmp_locale, | |
152 | new nonfinite_num_get<CharType>(trap_infinity)); | |
153 | ||
154 | std::basic_stringstream<CharType> ss; | |
155 | ss.imbue(new_locale); | |
156 | ||
157 | ValType a1 = std::numeric_limits<ValType>::infinity(); | |
158 | ss << a1; | |
159 | ValType b1; | |
160 | ss >> b1; | |
161 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); | |
162 | ||
163 | ss.clear(); | |
164 | ss.str(S_("")); | |
165 | ||
166 | ValType a2 = -std::numeric_limits<ValType>::infinity(); | |
167 | ss << a2; | |
168 | ValType b2; | |
169 | ss >> b2; | |
170 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); | |
171 | } | |
172 | ||
173 | //------------------------------------------------------------------------------ | |
174 | ||
175 | template<class CharType, class ValType> void trap_test_nan_impl(); | |
176 | template<class CharType, class ValType> void trap_test_put_nan_impl(); | |
177 | template<class CharType, class ValType> void trap_test_get_nan_impl(); | |
178 | ||
179 | void trap_test_nan() | |
180 | { // Test NaN using all the built-in char and floating-point types. | |
181 | trap_test_nan_impl<char, float>(); | |
182 | trap_test_nan_impl<char, double>(); | |
183 | trap_test_nan_impl<char, long double>(); | |
184 | trap_test_nan_impl<wchar_t, float>(); | |
185 | trap_test_nan_impl<wchar_t, double>(); | |
186 | trap_test_nan_impl<wchar_t, long double>(); | |
187 | } | |
188 | ||
189 | template<class CharType, class ValType> void trap_test_nan_impl() | |
190 | { | |
191 | trap_test_put_nan_impl<CharType, ValType>(); | |
192 | trap_test_get_nan_impl<CharType, ValType>(); | |
193 | } | |
194 | ||
195 | template<class CharType, class ValType> void trap_test_put_nan_impl() | |
196 | { | |
197 | std::locale old_locale; | |
198 | std::locale new_locale(old_locale, | |
199 | new nonfinite_num_put<CharType>(trap_nan)); | |
200 | ||
201 | std::basic_stringstream<CharType> ss; | |
202 | ss.imbue(new_locale); | |
203 | ||
204 | ValType a1 = std::numeric_limits<ValType>::quiet_NaN(); | |
205 | ss << a1; | |
206 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit | |
207 | || ss.rdstate() == std::ios_base::badbit); | |
208 | ss.clear(); | |
209 | ||
210 | ValType a2 = std::numeric_limits<ValType>::signaling_NaN(); | |
211 | ss << a2; | |
212 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit | |
213 | || ss.rdstate() == std::ios_base::badbit); | |
214 | } | |
215 | ||
216 | template<class CharType, class ValType> void trap_test_get_nan_impl() | |
217 | { | |
218 | std::locale old_locale; | |
219 | std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>); | |
220 | std::locale new_locale(tmp_locale, | |
221 | new nonfinite_num_get<CharType>(trap_nan)); | |
222 | ||
223 | std::basic_stringstream<CharType> ss; | |
224 | ss.imbue(new_locale); | |
225 | ||
226 | ValType a1 = std::numeric_limits<ValType>::quiet_NaN(); | |
227 | ss << a1; | |
228 | ValType b1; | |
229 | ss >> b1; | |
230 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); | |
231 | ||
232 | ss.clear(); | |
233 | ss.str(S_("")); | |
234 | ||
235 | ValType a2 = std::numeric_limits<ValType>::signaling_NaN(); | |
236 | ss << a2; | |
237 | ValType b2; | |
238 | ss >> b2; | |
239 | BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); | |
240 | } | |
241 | ||
242 | //------------------------------------------------------------------------------ | |
243 | ||
244 | // Test a selection of stream output options comparing result with expected string. | |
245 | // Only uses CharType = char and ValType = double. | |
246 | // Other types have already been tested above. | |
247 | ||
248 | #define CHECKOUT(manips, expected)\ | |
249 | {\ | |
250 | std::locale old_locale;\ | |
251 | std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(0)); /* default flags. */\ | |
252 | std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);\ | |
253 | std::ostringstream ss;\ | |
254 | ss.imbue(new_locale);\ | |
255 | ss << manips;\ | |
256 | std::basic_string<char> s = S_(expected);\ | |
257 | BOOST_CHECK_EQUAL(ss.str(), s);\ | |
258 | }\ | |
259 | ||
260 | BOOST_AUTO_TEST_CASE(check_trap_nan) | |
261 | { // Check that with trap_nan set, it really does throw exception. | |
262 | std::locale old_locale; | |
263 | std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(trap_nan)); | |
264 | std::locale new_locale(tmp_locale, new nonfinite_num_get<char>); | |
265 | std::ostringstream os; | |
266 | os.imbue(new_locale); | |
267 | os.exceptions(std::ios_base::badbit | std::ios_base::failbit); // Enable throwing exceptions. | |
268 | double nan = std::numeric_limits<double>::quiet_NaN(); | |
269 | BOOST_MATH_CHECK_THROW((os << nan), std::runtime_error); | |
270 | // warning : in "check_trap_nan": exception std::runtime_error is expected | |
271 | } // BOOST_AUTO_TEST_CASE(check_trap_nan) | |
272 | ||
273 | BOOST_AUTO_TEST_CASE(check_trap_inf) | |
274 | { // Check that with trap_nan set, it really does throw exception. | |
275 | std::locale old_locale; | |
276 | std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(trap_infinity)); | |
277 | std::locale new_locale(tmp_locale, new nonfinite_num_get<char>); | |
278 | std::ostringstream os; | |
279 | os.imbue(new_locale); | |
280 | os.exceptions(std::ios_base::badbit | std::ios_base::failbit); // Enable throwing exceptions. | |
281 | double inf = std::numeric_limits<double>::infinity(); | |
282 | BOOST_MATH_CHECK_THROW((os << inf), std::runtime_error); | |
283 | // warning : in "check_trap_inf": exception std::runtime_error is expected. | |
284 | ||
285 | } // BOOST_AUTO_TEST_CASE(check_trap_nan_inf) | |
286 | ||
287 | BOOST_AUTO_TEST_CASE(output_tests) | |
288 | { | |
289 | // Positive zero. | |
290 | CHECKOUT(0, "0"); // integer zero. | |
291 | CHECKOUT(0., "0"); // double zero. | |
292 | ||
293 | double nan = std::numeric_limits<double>::quiet_NaN(); | |
294 | double inf = std::numeric_limits<double>::infinity(); | |
295 | ||
296 | CHECKOUT(inf, "inf"); // infinity. | |
297 | CHECKOUT(-inf, "-inf"); // infinity. | |
298 | CHECKOUT(std::showpos << inf, "+inf"); // infinity. | |
299 | ||
300 | CHECKOUT(std::setw(6) << std::showpos << inf, " +inf"); // infinity. | |
301 | CHECKOUT(std::right << std::setw(6) << std::showpos << inf, " +inf"); // infinity. | |
302 | CHECKOUT(std::left << std::setw(6) << std::showpos << inf, "+inf "); // infinity. | |
303 | CHECKOUT(std::left << std::setw(6) << std::setprecision(6) << inf, "inf "); // infinity. | |
304 | CHECKOUT(std::left << std::setw(6) << std::setfill('*') << std::setprecision(6) << inf, "inf***"); // infinity. | |
305 | CHECKOUT(std::right << std::setw(6) << std::setfill('*') << std::setprecision(6) << inf, "***inf"); // infinity. | |
306 | CHECKOUT(std::internal<< std::setw(6) << std::showpos << inf, "+ inf"); // infinity. | |
307 | CHECKOUT(std::internal<< std::setw(6) << std::setfill('*') << std::showpos << inf, "+**inf"); // infinity. | |
308 | CHECKOUT(std::internal<< std::setw(6) << std::setfill('*') << std::showpos << -inf, "-**inf"); // infinity. | |
309 | ||
310 | CHECKOUT(nan, "nan"); // nan | |
311 | CHECKOUT(std::setw(1) << nan, "nan"); // nan, even if width was too small. | |
312 | CHECKOUT(std::setprecision(10) << nan, "nan"); // setprecision has no effect. | |
313 | } // BOOST_AUTO_TEST_CASE(output_tests) | |
314 | ||
315 | } // anonymous namespace | |
316 | ||
317 | /* | |
318 | ||
319 | Output: | |
320 | ||
321 | test_nonfinite_io.cpp | |
322 | test_nonfinite_io.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\test_nonfinite_io.exe | |
323 | Running 4 test cases... | |
324 | Platform: Win32 | |
325 | Compiler: Microsoft Visual C++ version 10.0 | |
326 | STL : Dinkumware standard library version 520 | |
327 | Boost : 1.49.0 | |
328 | Entering test suite "Master Test Suite" | |
329 | Entering test case "trap_test" | |
330 | Leaving test case "trap_test"; testing time: 7ms | |
331 | Entering test case "check_trap_nan" | |
332 | Leaving test case "check_trap_nan" | |
333 | Entering test case "check_trap_inf" | |
334 | Leaving test case "check_trap_inf"; testing time: 1ms | |
335 | Entering test case "output_tests" | |
336 | Leaving test case "output_tests"; testing time: 3ms | |
337 | Leaving test suite "Master Test Suite" | |
338 | ||
339 | *** No errors detected | |
340 | ||
341 | */ | |
342 |