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 #define BOOST_INCLUDE_MAIN
13 #include <boost/test/test_tools.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; }
55 #endif
56 
57 #if (defined(_GLIBCPP_VERSION) || defined(_GLIBCXX_VERSION)) \
58    && defined(BOOST_HAS_LONG_LONG) \
59    && !defined(_GLIBCPP_USE_LONG_LONG) \
60    && !defined(_GLIBCXX_USE_LONG_LONG)
61 //
62 // Some libstdc++ versions have numeric_limits<long long> but no
63 // iostream support for long long.  TODO, find a better fix!!
64 //
operator <<(std::ostream & os,long long i)65 std::ostream& operator<<(std::ostream& os, long long i )
66 {
67     return os << static_cast<long double>(i);
68 }
operator <<(std::ostream & os,unsigned long long i)69 std::ostream& operator<<(std::ostream& os, unsigned long long i )
70 {
71     return os << static_cast<long double>(i);
72 }
73 #endif
74 
75 template<class T>
test_integral_limits(const T &,const char * msg)76 void test_integral_limits(const T &, const char * msg)
77 {
78   typedef std::numeric_limits<T> lim;
79   std::cout << "Testing " << msg
80             << " (size " << sizeof(T) << ")"
81             << " min: " << make_char_numeric_for_streaming((lim::min)())
82             << ", max: " << make_char_numeric_for_streaming((lim::max)())
83             << std::endl;
84 
85   BOOST_CHECK(static_cast<bool>(lim::is_specialized));
86   BOOST_CHECK(static_cast<bool>(lim::is_integer));
87   // BOOST_CHECK(lim::is_modulo);
88   BOOST_CHECK(static_cast<bool>((lim::min)() < (lim::max)()));
89 }
90 
91 template <class T>
print_hex_val(T t,const char * name)92 void print_hex_val(T t, const char* name)
93 {
94   const unsigned char* p = (const unsigned char*)&t;
95   std::cout << "hex value of " << name << " is: ";
96   for (unsigned int i = 0; i < sizeof(T); ++i) {
97     if(p[i] <= 0xF)
98       std::cout << "0";
99     std::cout << std::hex << (int)p[i];
100   }
101   std::cout << std::dec << std::endl;
102 }
103 
104 template<class T>
test_float_limits(const T &,const char * msg)105 void test_float_limits(const T &, const char * msg)
106 {
107   std::cout << "\nTesting " << msg << std::endl;
108   typedef std::numeric_limits<T> lim;
109 
110   BOOST_CHECK(static_cast<bool>(lim::is_specialized));
111   BOOST_CHECK(static_cast<bool>(!lim::is_modulo));
112   BOOST_CHECK(static_cast<bool>(!lim::is_integer));
113   BOOST_CHECK(static_cast<bool>(lim::is_signed));
114 
115   const T infinity = lim::infinity();
116   const T qnan = lim::quiet_NaN();
117   const T snan = lim::signaling_NaN();
118 
119   std::cout << "IEEE-compatible: " << lim::is_iec559
120        << ", traps: " << lim::traps
121        << ", bounded: " << lim::is_bounded
122        << ", exact: " << lim::is_exact << '\n'
123        << "min: " << (lim::min)() << ", max: " << (lim::max)() << '\n'
124        << "infinity: " << infinity << ", QNaN: " << qnan << '\n';
125   print_hex_val((lim::max)(), "max");
126   print_hex_val(infinity, "infinity");
127   print_hex_val(qnan, "qnan");
128   print_hex_val(snan, "snan");
129 
130   BOOST_CHECK((lim::max)() > 1000);
131   BOOST_CHECK((lim::min)() > 0);
132   BOOST_CHECK((lim::min)() < 0.001);
133   BOOST_CHECK(lim::epsilon() > 0);
134 
135   if(lim::is_iec559) {
136     BOOST_CHECK(static_cast<bool>(lim::has_infinity));
137     BOOST_CHECK(static_cast<bool>(lim::has_quiet_NaN));
138     BOOST_CHECK(static_cast<bool>(lim::has_signaling_NaN));
139   } else {
140     std::cout << "Does not claim IEEE conformance" << std::endl;
141   }
142 
143   if(lim::has_infinity) {
144     // Make sure those values are not 0 or similar nonsense.
145     // Infinity must compare as if larger than the maximum representable value.
146     BOOST_CHECK(infinity > (lim::max)());
147     BOOST_CHECK(-infinity < -(lim::max)());
148   } else {
149     std::cout << "Does not have infinity" << std::endl;
150   }
151 
152   if(lim::has_quiet_NaN) {
153     // NaNs shall always compare "false" when compared for equality
154     // If one of these fail, your compiler may be optimizing incorrectly,
155     // or the standard library is incorrectly configured.
156     BOOST_CHECK(! (qnan == 42));
157     BOOST_CHECK(qnan != 42);
158     if(lim::is_iec559)
159     {
160       BOOST_CHECK(! (qnan == qnan));
161       BOOST_CHECK(qnan != qnan);
162     }
163 
164     // The following tests may cause arithmetic traps.
165     // BOOST_CHECK(! (qnan < 42));
166     // BOOST_CHECK(! (qnan > 42));
167     // BOOST_CHECK(! (qnan <= 42));
168     // BOOST_CHECK(! (qnan >= 42));
169   } else {
170     std::cout << "Does not have QNaN" << std::endl;
171   }
172 }
173 
174 
test_main(int,char * [])175 int test_main(int, char*[])
176 {
177   test_integral_limits(bool(), "bool");
178   test_integral_limits(char(), "char");
179   typedef signed char signed_char;
180   test_integral_limits(signed_char(), "signed char");
181   typedef unsigned char unsigned_char;
182   test_integral_limits(unsigned_char(), "unsigned char");
183   test_integral_limits(wchar_t(), "wchar_t");
184   test_integral_limits(short(), "short");
185   typedef unsigned short unsigned_short;
186   test_integral_limits(unsigned_short(), "unsigned short");
187   test_integral_limits(int(), "int");
188   typedef unsigned int unsigned_int;
189   test_integral_limits(unsigned_int(), "unsigned int");
190   test_integral_limits(long(), "long");
191   typedef unsigned long unsigned_long;
192   test_integral_limits(unsigned_long(), "unsigned long");
193 #if defined(BOOST_HAS_LONG_LONG)
194   test_integral_limits(::boost::long_long_type(), "long long");
195   test_integral_limits(::boost::ulong_long_type(), "unsigned long long");
196 #endif
197 #ifdef BOOST_HAS_MS_INT64
198   typedef __int64 long_long2;
199   test_integral_limits(long_long2(), "__int64");
200   typedef unsigned __int64 unsigned_long_long2;
201   test_integral_limits(unsigned_long_long2(), "unsigned __int64");
202 #endif
203 
204   test_float_limits(float(), "float");
205   test_float_limits(double(), "double");
206   typedef long double long_double;
207   test_float_limits(long_double(), "long double");
208   // Some compilers don't pay attention to std:3.6.1/5 and issue a
209   // warning here if "return 0;" is omitted.
210   return 0;
211 }
212 
213 
214