1 | // Unit test for boost::lexical_cast. |
2 | // |
3 | // See http://www.boost.org for most recent version, including documentation. |
4 | // |
5 | // Copyright Antony Polukhin, 2011-2024. |
6 | // |
7 | // Distributed under the Boost |
8 | // Software License, Version 1.0. (See accompanying file |
9 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). |
10 | |
11 | #include <boost/lexical_cast.hpp> |
12 | |
13 | #include <boost/core/cmath.hpp> |
14 | #include <boost/type_traits/is_same.hpp> |
15 | |
16 | #include <boost/core/lightweight_test.hpp> |
17 | |
18 | #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) |
19 | #define BOOST_LCAST_NO_WCHAR_T |
20 | #endif |
21 | |
22 | using namespace boost; |
23 | |
24 | template <class T> |
25 | bool is_pos_inf(T value) |
26 | { |
27 | return (boost::core::isinf)(value) && !(boost::core::signbit)(value); |
28 | } |
29 | |
30 | template <class T> |
31 | bool is_neg_inf(T value) |
32 | { |
33 | return (boost::core::isinf)(value) && (boost::core::signbit)(value); |
34 | } |
35 | |
36 | template <class T> |
37 | bool is_pos_nan(T value) |
38 | { |
39 | return (boost::core::isnan)(value) && !(boost::core::signbit)(value); |
40 | } |
41 | |
42 | template <class T> |
43 | bool is_neg_nan(T value) |
44 | { |
45 | /* There is some strange behaviour on Itanium platform with -nan nuber for long double. |
46 | * It is a IA64 feature, or it is a boost::math feature, not a lexical_cast bug */ |
47 | #if defined(__ia64__) || defined(_M_IA64) |
48 | return (boost::core::isnan)(value) |
49 | && ( boost::is_same<T, long double >::value || (boost::core::signbit)(value) ); |
50 | #else |
51 | return (boost::core::isnan)(value) && (boost::core::signbit)(value); |
52 | #endif |
53 | } |
54 | |
55 | template <class T> |
56 | void test_inf_nan_templated() |
57 | { |
58 | typedef T test_t; |
59 | |
60 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("inf" ) ) ); |
61 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("INF" ) ) ); |
62 | |
63 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-inf" ) ) ); |
64 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-INF" ) ) ); |
65 | |
66 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("+inf" ) ) ); |
67 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("+INF" ) ) ); |
68 | |
69 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("infinity" ) ) ); |
70 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("INFINITY" ) ) ); |
71 | |
72 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-infinity" ) ) ); |
73 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-INFINITY" ) ) ); |
74 | |
75 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("+infinity" ) ) ); |
76 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("+INFINITY" ) ) ); |
77 | |
78 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("iNfiNity" ) ) ); |
79 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>("INfinity" ) ) ); |
80 | |
81 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-inFINITY" ) ) ); |
82 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>("-INFINITY" ) ) ); |
83 | |
84 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("nan" ) ) ); |
85 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("NAN" ) ) ); |
86 | |
87 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>("-nan" ) ) ); |
88 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>("-NAN" ) ) ); |
89 | |
90 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("+nan" ) ) ); |
91 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("+NAN" ) ) ); |
92 | |
93 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("nAn" ) ) ); |
94 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("NaN" ) ) ); |
95 | |
96 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>("-nAn" ) ) ); |
97 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>("-NaN" ) ) ); |
98 | |
99 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("+Nan" ) ) ); |
100 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("+nAN" ) ) ); |
101 | |
102 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("nan()" ) ) ); |
103 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>("NAN(some string)" ) ) ); |
104 | BOOST_TEST_THROWS( lexical_cast<test_t>("NAN(some string" ), bad_lexical_cast ); |
105 | |
106 | BOOST_TEST(lexical_cast<std::string>( (boost::core::copysign)(std::numeric_limits<test_t >::infinity(), static_cast<test_t>(-1.0))) |
107 | == "-inf" ); |
108 | BOOST_TEST(lexical_cast<std::string>( std::numeric_limits<test_t >::infinity()) == "inf" ); |
109 | BOOST_TEST(lexical_cast<std::string>( std::numeric_limits<test_t >::quiet_NaN()) == "nan" ); |
110 | #if !defined(__ia64__) && !defined(_M_IA64) |
111 | BOOST_TEST(lexical_cast<std::string>( |
112 | (boost::core::copysign)(std::numeric_limits<test_t >::quiet_NaN(), static_cast<test_t>(-1.0))) |
113 | == "-nan" ); |
114 | #endif |
115 | |
116 | #ifndef BOOST_LCAST_NO_WCHAR_T |
117 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"inf" ) ) ); |
118 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"INF" ) ) ); |
119 | |
120 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-inf" ) ) ); |
121 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-INF" ) ) ); |
122 | |
123 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+inf" ) ) ); |
124 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+INF" ) ) ); |
125 | |
126 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"infinity" ) ) ); |
127 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"INFINITY" ) ) ); |
128 | |
129 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-infinity" ) ) ); |
130 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-INFINITY" ) ) ); |
131 | |
132 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+infinity" ) ) ); |
133 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+INFINITY" ) ) ); |
134 | |
135 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-infINIty" ) ) ); |
136 | BOOST_TEST( is_neg_inf( lexical_cast<test_t>(L"-INFiniTY" ) ) ); |
137 | |
138 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+inFINIty" ) ) ); |
139 | BOOST_TEST( is_pos_inf( lexical_cast<test_t>(L"+INfinITY" ) ) ); |
140 | |
141 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"nan" ) ) ); |
142 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"NAN" ) ) ); |
143 | |
144 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>(L"-nan" ) ) ); |
145 | BOOST_TEST( is_neg_nan( lexical_cast<test_t>(L"-NAN" ) ) ); |
146 | |
147 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"+nan" ) ) ); |
148 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"+NAN" ) ) ); |
149 | |
150 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"nan()" ) ) ); |
151 | BOOST_TEST( is_pos_nan( lexical_cast<test_t>(L"NAN(some string)" ) ) ); |
152 | BOOST_TEST_THROWS( lexical_cast<test_t>(L"NAN(some string" ), bad_lexical_cast ); |
153 | |
154 | BOOST_TEST(lexical_cast<std::wstring>( (boost::core::copysign)(std::numeric_limits<test_t >::infinity(), static_cast<test_t>(-1.0))) |
155 | == L"-inf" ); |
156 | BOOST_TEST(lexical_cast<std::wstring>( std::numeric_limits<test_t >::infinity()) == L"inf" ); |
157 | BOOST_TEST(lexical_cast<std::wstring>( std::numeric_limits<test_t >::quiet_NaN()) == L"nan" ); |
158 | #if !defined(__ia64__) && !defined(_M_IA64) |
159 | BOOST_TEST(lexical_cast<std::wstring>( |
160 | (boost::core::copysign)(std::numeric_limits<test_t >::quiet_NaN(), static_cast<test_t>(-1.0))) |
161 | == L"-nan" ); |
162 | #endif |
163 | |
164 | #endif |
165 | } |
166 | |
167 | void test_inf_nan_float() |
168 | { |
169 | test_inf_nan_templated<float >(); |
170 | |
171 | BOOST_TEST(is_pos_nan(lexical_cast<float>(std::numeric_limits<float>::quiet_NaN()))); |
172 | BOOST_TEST(is_neg_nan(lexical_cast<float>(-std::numeric_limits<float>::quiet_NaN()))); |
173 | BOOST_TEST(is_pos_inf(lexical_cast<float>(std::numeric_limits<float>::infinity()))); |
174 | BOOST_TEST(is_neg_inf(lexical_cast<float>(-std::numeric_limits<float>::infinity()))); |
175 | |
176 | BOOST_TEST(is_pos_nan(lexical_cast<float>(std::numeric_limits<double>::quiet_NaN()))); |
177 | BOOST_TEST(is_neg_nan(lexical_cast<float>(-std::numeric_limits<double>::quiet_NaN()))); |
178 | BOOST_TEST(is_pos_inf(lexical_cast<float>(std::numeric_limits<double>::infinity()))); |
179 | BOOST_TEST(is_neg_inf(lexical_cast<float>(-std::numeric_limits<double>::infinity()))); |
180 | } |
181 | |
182 | void test_inf_nan_double() |
183 | { |
184 | test_inf_nan_templated<double >(); |
185 | |
186 | BOOST_TEST(is_pos_nan(lexical_cast<double>(std::numeric_limits<float>::quiet_NaN()))); |
187 | BOOST_TEST(is_neg_nan(lexical_cast<double>(-std::numeric_limits<float>::quiet_NaN()))); |
188 | BOOST_TEST(is_pos_inf(lexical_cast<double>(std::numeric_limits<float>::infinity()))); |
189 | BOOST_TEST(is_neg_inf(lexical_cast<double>(-std::numeric_limits<float>::infinity()))); |
190 | |
191 | BOOST_TEST(is_pos_nan(lexical_cast<double>(std::numeric_limits<double>::quiet_NaN()))); |
192 | BOOST_TEST(is_neg_nan(lexical_cast<double>(-std::numeric_limits<double>::quiet_NaN()))); |
193 | BOOST_TEST(is_pos_inf(lexical_cast<double>(std::numeric_limits<double>::infinity()))); |
194 | BOOST_TEST(is_neg_inf(lexical_cast<double>(-std::numeric_limits<double>::infinity()))); |
195 | |
196 | BOOST_TEST(is_pos_nan(lexical_cast<double>(std::numeric_limits<long double>::quiet_NaN()))); |
197 | BOOST_TEST(is_neg_nan(lexical_cast<double>(-std::numeric_limits<long double>::quiet_NaN()))); |
198 | BOOST_TEST(is_pos_inf(lexical_cast<double>(std::numeric_limits<long double>::infinity()))); |
199 | BOOST_TEST(is_neg_inf(lexical_cast<double>(-std::numeric_limits<long double>::infinity()))); |
200 | } |
201 | |
202 | void test_inf_nan_long_double() |
203 | { |
204 | // We do not run tests on compilers with bugs |
205 | #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
206 | test_inf_nan_templated<long double >(); |
207 | #endif |
208 | BOOST_TEST(true); |
209 | } |
210 | |
211 | int main() |
212 | { |
213 | test_inf_nan_float(); |
214 | test_inf_nan_double(); |
215 | test_inf_nan_long_double(); |
216 | |
217 | return boost::report_errors(); |
218 | } |
219 | |