1 /* boost limits_test.cpp test your <limits> file for important
2 *
3 * Copyright Jens Maurer 2000
4 * Distributed under the Boost Software License, Version 1.0. (See
5 * accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 * $Id$
9 */
10
11 #include <boost/limits.hpp>
12 #include <boost/detail/lightweight_main.hpp>
13 #include <boost/core/lightweight_test.hpp>
14 #include <iostream>
15
16 /*
17 * General portability note:
18 * MSVC mis-compiles explicit function template instantiations.
19 * For example, f<A>() and f<B>() are both compiled to call f<A>().
20 * BCC is unable to implicitly convert a "const char *" to a std::string
21 * when using explicit function template instantiations.
22 *
23 * Therefore, avoid explicit function template instantiations.
24 */
25 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
make_char_numeric_for_streaming(T x)26 template<typename T> inline T make_char_numeric_for_streaming(T x) { return x; }
27 namespace fix{
make_char_numeric_for_streaming(char c)28 inline int make_char_numeric_for_streaming(char c) { return c; }
make_char_numeric_for_streaming(signed char c)29 inline int make_char_numeric_for_streaming(signed char c) { return c; }
make_char_numeric_for_streaming(unsigned char c)30 inline int make_char_numeric_for_streaming(unsigned char c) { return c; }
31 }
32 using namespace fix;
33 # if defined(_YVALS) && !defined(_CPPLIB_VER) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
34 // fix for missing operator<< in original Dinkumware lib:
operator <<(std::ostream & os,__int64 i)35 std::ostream& operator<<(std::ostream& os, __int64 i )
36 {
37 char buf[80];
38 sprintf(buf,"%I64d", i );
39 os << buf;
40 return os;
41 }
operator <<(std::ostream & os,unsigned __int64 i)42 std::ostream& operator<<(std::ostream& os, unsigned __int64 i )
43 {
44 char buf[80];
45 sprintf(buf,"%I64u", i );
46 os << buf;
47 return os;
48 }
49 # endif
50 #else
make_char_numeric_for_streaming(T x)51 template<typename T> inline T make_char_numeric_for_streaming(T x) { return x; }
make_char_numeric_for_streaming(char c)52 inline int make_char_numeric_for_streaming(char c) { return c; }
make_char_numeric_for_streaming(signed char c)53 inline int make_char_numeric_for_streaming(signed char c) { return c; }
make_char_numeric_for_streaming(unsigned char c)54 inline int make_char_numeric_for_streaming(unsigned char c) { return c; }
make_char_numeric_for_streaming(wchar_t c)55 inline int make_char_numeric_for_streaming(wchar_t c) { return c; }
56 #endif
57
58 #if (defined(_GLIBCPP_VERSION) || defined(_GLIBCXX_VERSION)) \
59 && defined(BOOST_HAS_LONG_LONG) \
60 && !defined(_GLIBCPP_USE_LONG_LONG) \
61 && !defined(_GLIBCXX_USE_LONG_LONG)
62 //
63 // Some libstdc++ versions have numeric_limits<long long> but no
64 // iostream support for long long. TODO, find a better fix!!
65 //
operator <<(std::ostream & os,long long i)66 std::ostream& operator<<(std::ostream& os, long long i )
67 {
68 return os << static_cast<long double>(i);
69 }
operator <<(std::ostream & os,unsigned long long i)70 std::ostream& operator<<(std::ostream& os, unsigned long long i )
71 {
72 return os << static_cast<long double>(i);
73 }
74 #endif
75
76 template<class T>
test_integral_limits(const T &,const char * msg)77 void test_integral_limits(const T &, const char * msg)
78 {
79 typedef std::numeric_limits<T> lim;
80 std::cout << "Testing " << msg
81 << " (size " << sizeof(T) << ")"
82 << " min: " << make_char_numeric_for_streaming((lim::min)())
83 << ", max: " << make_char_numeric_for_streaming((lim::max)())
84 << std::endl;
85
86 BOOST_TEST(static_cast<bool>(lim::is_specialized));
87 BOOST_TEST(static_cast<bool>(lim::is_integer));
88 // BOOST_TEST(lim::is_modulo);
89 BOOST_TEST(static_cast<bool>((lim::min)() < (lim::max)()));
90 }
91
92 template <class T>
print_hex_val(T t,const char * name)93 void print_hex_val(T t, const char* name)
94 {
95 const unsigned char* p = (const unsigned char*)&t;
96 std::cout << "hex value of " << name << " is: ";
97 for (unsigned int i = 0; i < sizeof(T); ++i) {
98 if(p[i] <= 0xF)
99 std::cout << "0";
100 std::cout << std::hex << (int)p[i];
101 }
102 std::cout << std::dec << std::endl;
103 }
104
105 template<class T>
test_float_limits(const T &,const char * msg)106 void test_float_limits(const T &, const char * msg)
107 {
108 std::cout << "\nTesting " << msg << std::endl;
109 typedef std::numeric_limits<T> lim;
110
111 BOOST_TEST(static_cast<bool>(lim::is_specialized));
112 BOOST_TEST(static_cast<bool>(!lim::is_modulo));
113 BOOST_TEST(static_cast<bool>(!lim::is_integer));
114 BOOST_TEST(static_cast<bool>(lim::is_signed));
115
116 const T infinity = lim::infinity();
117 const T qnan = lim::quiet_NaN();
118 const T snan = lim::signaling_NaN();
119
120 std::cout << "IEEE-compatible: " << lim::is_iec559
121 << ", traps: " << lim::traps
122 << ", bounded: " << lim::is_bounded
123 << ", exact: " << lim::is_exact << '\n'
124 << "min: " << (lim::min)() << ", max: " << (lim::max)() << '\n'
125 << "infinity: " << infinity << ", QNaN: " << qnan << '\n';
126 print_hex_val((lim::max)(), "max");
127 print_hex_val(infinity, "infinity");
128 print_hex_val(qnan, "qnan");
129 print_hex_val(snan, "snan");
130
131 BOOST_TEST((lim::max)() > 1000);
132 BOOST_TEST((lim::min)() > 0);
133 BOOST_TEST((lim::min)() < 0.001);
134 BOOST_TEST(lim::epsilon() > 0);
135
136 if(lim::is_iec559) {
137 BOOST_TEST(static_cast<bool>(lim::has_infinity));
138 BOOST_TEST(static_cast<bool>(lim::has_quiet_NaN));
139 BOOST_TEST(static_cast<bool>(lim::has_signaling_NaN));
140 } else {
141 std::cout << "Does not claim IEEE conformance" << std::endl;
142 }
143
144 if(lim::has_infinity) {
145 // Make sure those values are not 0 or similar nonsense.
146 // Infinity must compare as if larger than the maximum representable value.
147 BOOST_TEST(infinity > (lim::max)());
148 BOOST_TEST(-infinity < -(lim::max)());
149 } else {
150 std::cout << "Does not have infinity" << std::endl;
151 }
152
153 if(lim::has_quiet_NaN) {
154 // NaNs shall always compare "false" when compared for equality
155 // If one of these fail, your compiler may be optimizing incorrectly,
156 // or the standard library is incorrectly configured.
157 BOOST_TEST(! (qnan == 42));
158 BOOST_TEST(qnan != 42);
159 if(lim::is_iec559)
160 {
161 BOOST_TEST(! (qnan == qnan));
162 BOOST_TEST(qnan != qnan);
163 }
164
165 // The following tests may cause arithmetic traps.
166 // BOOST_TEST(! (qnan < 42));
167 // BOOST_TEST(! (qnan > 42));
168 // BOOST_TEST(! (qnan <= 42));
169 // BOOST_TEST(! (qnan >= 42));
170 } else {
171 std::cout << "Does not have QNaN" << std::endl;
172 }
173 }
174
175
cpp_main(int,char * [])176 int cpp_main(int, char*[])
177 {
178 test_integral_limits(bool(), "bool");
179 test_integral_limits(char(), "char");
180 typedef signed char signed_char;
181 test_integral_limits(signed_char(), "signed char");
182 typedef unsigned char unsigned_char;
183 test_integral_limits(unsigned_char(), "unsigned char");
184 test_integral_limits(wchar_t(), "wchar_t");
185 test_integral_limits(short(), "short");
186 typedef unsigned short unsigned_short;
187 test_integral_limits(unsigned_short(), "unsigned short");
188 test_integral_limits(int(), "int");
189 typedef unsigned int unsigned_int;
190 test_integral_limits(unsigned_int(), "unsigned int");
191 test_integral_limits(long(), "long");
192 typedef unsigned long unsigned_long;
193 test_integral_limits(unsigned_long(), "unsigned long");
194 #if defined(BOOST_HAS_LONG_LONG)
195 test_integral_limits(::boost::long_long_type(), "long long");
196 test_integral_limits(::boost::ulong_long_type(), "unsigned long long");
197 #endif
198 #ifdef BOOST_HAS_MS_INT64
199 typedef __int64 long_long2;
200 test_integral_limits(long_long2(), "__int64");
201 typedef unsigned __int64 unsigned_long_long2;
202 test_integral_limits(unsigned_long_long2(), "unsigned __int64");
203 #endif
204
205 test_float_limits(float(), "float");
206 test_float_limits(double(), "double");
207 typedef long double long_double;
208 test_float_limits(long_double(), "long double");
209 // Some compilers don't pay attention to std:3.6.1/5 and issue a
210 // warning here if "return 0;" is omitted.
211 return boost::report_errors();
212 }
213
214
215