Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlimits_test.cpp
Go to the documentation of this file.
00001 /* boost limits_test.cpp test your <limits> file for important 00002 * 00003 * Copyright Jens Maurer 2000 00004 * Permission to use, copy, modify, sell, and distribute this software 00005 * is hereby granted without fee provided that the above copyright notice 00006 * appears in all copies and that both that copyright notice and this 00007 * permission notice appear in supporting documentation, 00008 * 00009 * Jens Maurer makes no representations about the suitability of this 00010 * software for any purpose. It is provided "as is" without express or 00011 * implied warranty. 00012 * 00013 */ 00014 00015 #include <limits> 00016 //#include <sstream> 00017 00018 #include "cppunit/cppunit_proxy.h" 00019 00020 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) 00021 using namespace std; 00022 #endif 00023 00024 // 00025 // TestCase class 00026 // 00027 class LimitTest : public CPPUNIT_NS::TestCase 00028 { 00029 CPPUNIT_TEST_SUITE(LimitTest); 00030 # if defined (__BORLANDC__) 00031 /* Ignore FPU exceptions, set FPU precision to 64 bits */ 00032 unsigned int _float_control_word = _control87(0, 0); 00033 _control87(PC_64|MCW_EM|IC_AFFINE, MCW_PC|MCW_EM|MCW_IC); 00034 # endif 00035 CPPUNIT_TEST(test); 00036 CPPUNIT_TEST(qnan_test); 00037 # if defined (__BORLANDC__) 00038 /* Reset floating point control word */ 00039 _clear87(); 00040 _control87(_float_control_word, MCW_PC|MCW_EM|MCW_IC); 00041 # endif 00042 CPPUNIT_TEST_SUITE_END(); 00043 00044 protected: 00045 void test(); 00046 void qnan_test(); 00047 }; 00048 00049 CPPUNIT_TEST_SUITE_REGISTRATION(LimitTest); 00050 00051 #if defined (STLPORT) && defined (_STLP_STATIC_CONST_INIT_BUG) 00052 # define CHECK_COND(X) if (!(X)) { CPPUNIT_MESSAGE(#X); return false; } 00053 #else 00054 //This version force to have external linkage on static constant which might 00055 //reveal that _STLP_NO_STATIC_CONST_DEFINITION should be commented. 00056 bool check_cond(const bool& cond) { return cond; } 00057 # define CHECK_COND(X) if (!check_cond(X)) { CPPUNIT_MESSAGE(#X); return false; } 00058 #endif 00059 00060 bool valid_sign_info(bool, bool) 00061 { return true; } 00062 00063 template <class _Tp> 00064 bool valid_sign_info(bool limit_is_signed, const _Tp &) { 00065 return (limit_is_signed && _Tp(-1) < 0) || 00066 (!limit_is_signed && _Tp(-1) > 0); 00067 } 00068 00069 template <class _Tp> 00070 bool test_integral_limits_base(const _Tp &, bool unknown_sign = true, bool is_signed = true) { 00071 typedef numeric_limits<_Tp> lim; 00072 00073 CHECK_COND(lim::is_specialized); 00074 CHECK_COND(lim::is_exact); 00075 CHECK_COND(lim::is_integer); 00076 CHECK_COND(!lim::is_iec559); 00077 CHECK_COND(lim::min() < lim::max()); 00078 CHECK_COND((unknown_sign && ((lim::is_signed && (lim::min() != 0)) || (!lim::is_signed && (lim::min() == 0)))) || 00079 (!unknown_sign && ((lim::is_signed && is_signed) || (!lim::is_signed && !is_signed)))); 00080 00081 if (unknown_sign) { 00082 CHECK_COND(valid_sign_info(lim::is_signed, _Tp())); 00083 } 00084 return true; 00085 } 00086 00087 template <class _Tp> 00088 bool test_integral_limits(const _Tp &val, bool unknown_sign = true, bool is_signed = true) { 00089 if (!test_integral_limits_base(val, unknown_sign, is_signed)) 00090 return false; 00091 00092 typedef numeric_limits<_Tp> lim; 00093 00094 CHECK_COND(lim::is_modulo); 00095 00096 if (lim::is_bounded || 00097 (!lim::is_bounded && !lim::is_signed)) { 00098 _Tp tmp = lim::min(); 00099 CHECK_COND( --tmp > lim::min() ); 00100 } 00101 00102 if (lim::is_bounded) { 00103 _Tp tmp = lim::max(); 00104 CHECK_COND( ++tmp < lim::max() ); 00105 } 00106 00107 return true; 00108 } 00109 00110 template <class _Tp> 00111 bool test_signed_integral_limits(const _Tp &__val) { 00112 return test_integral_limits(__val, false, true); 00113 } 00114 template <class _Tp> 00115 bool test_unsigned_integral_limits(const _Tp &__val) { 00116 return test_integral_limits(__val, false, false); 00117 } 00118 00119 template <class _Tp> 00120 bool test_float_values(_Tp lhs, _Tp rhs) 00121 { return lhs == rhs; } 00122 00123 template <class _Tp> 00124 bool test_float_limits(const _Tp &) { 00125 typedef numeric_limits<_Tp> lim; 00126 CHECK_COND(lim::is_specialized); 00127 CHECK_COND(!lim::is_modulo); 00128 CHECK_COND(!lim::is_integer); 00129 CHECK_COND(lim::is_signed); 00130 00131 CHECK_COND(lim::max() > 1000); 00132 CHECK_COND(lim::min() > 0); 00133 CHECK_COND(lim::min() < 0.001); 00134 CHECK_COND(lim::epsilon() > 0); 00135 00136 if (lim::is_iec559) { 00137 CHECK_COND(lim::has_infinity); 00138 CHECK_COND(lim::has_quiet_NaN); 00139 CHECK_COND(lim::has_signaling_NaN); 00140 CHECK_COND(lim::has_denorm == denorm_present); 00141 } 00142 00143 if (lim::has_denorm == denorm_absent) { 00144 CHECK_COND(lim::denorm_min() == lim::min()); 00145 _Tp tmp = lim::min(); 00146 tmp /= 2; 00147 if (tmp > 0 && tmp < lim::min()) { 00148 // has_denorm could be denorm_present 00149 CPPUNIT_MESSAGE("It looks like your compiler/platform supports denormalized floating point representation."); 00150 } 00151 } 00152 else if (lim::has_denorm == denorm_present) { 00153 CHECK_COND(lim::denorm_min() > 0); 00154 CHECK_COND(lim::denorm_min() < lim::min()); 00155 00156 _Tp tmp = lim::min(); 00157 while (tmp != 0) { 00158 _Tp old_tmp = tmp; 00159 tmp /= 2; 00160 CHECK_COND(tmp < old_tmp); 00161 CHECK_COND(tmp >= lim::denorm_min() || tmp == (_Tp)0); 00162 //ostringstream str; 00163 //str << "denorm_min = " << lim::denorm_min() << ", tmp = " << tmp; 00164 //CPPUNIT_MESSAGE(str.str().c_str()); 00165 } 00166 } 00167 00168 if (lim::has_infinity) { 00169 const _Tp infinity = lim::infinity(); 00170 /* Make sure those values are not 0 or similar nonsense. 00171 * Infinity must compare as if larger than the maximum representable value. */ 00172 00173 _Tp val = lim::max(); 00174 val *= 2; 00175 00176 /* We use test_float_values because without it some compilers (gcc) perform weird 00177 * optimization on the test giving unexpected result. */ 00178 CHECK_COND(test_float_values(val, infinity)); 00179 00180 /* 00181 ostringstream str; 00182 str << "lim::max() = " << lim::max() << ", val = " << val << ", infinity = " << infinity; 00183 CPPUNIT_MESSAGE( str.str().c_str() ); 00184 str.str(string()); 00185 str << "sizeof(_Tp) = " << sizeof(_Tp); 00186 CPPUNIT_MESSAGE( str.str().c_str() ); 00187 if (sizeof(_Tp) == 4) { 00188 str.str(string()); 00189 str << "val in hexa: " << showbase << hex << *((const unsigned int*)&val); 00190 str << ", infinity in hexa: " << showbase << hex << *((const unsigned int*)&infinity); 00191 } 00192 #if defined (_STLP_LONG_LONG) 00193 else if (sizeof(_Tp) == sizeof(_STLP_LONG_LONG)) { 00194 str.str(string()); 00195 str << "val in hexa: " << showbase << hex << *((const unsigned _STLP_LONG_LONG*)&val); 00196 str << ", infinity in hexa: " << showbase << hex << *((const unsigned _STLP_LONG_LONG*)&infinity); 00197 } 00198 #endif 00199 else { 00200 str.str(string()); 00201 str << "val: "; 00202 for (int i = 0; i != sizeof(_Tp) / sizeof(unsigned short); ++i) { 00203 if (i != 0) str << ' '; 00204 str << showbase << hex << setw(4) << setfill('0') << *((const unsigned short*)&val + i); 00205 } 00206 str << ", infinity: "; 00207 for (int i = 0; i != sizeof(_Tp) / sizeof(unsigned short); ++i) { 00208 if (i != 0) str << ' '; 00209 str << showbase << hex << setw(4) << setfill('0') << *((const unsigned short*)&infinity + i); 00210 } 00211 } 00212 CPPUNIT_MESSAGE( str.str().c_str() ); 00213 str.str(string()); 00214 str << dec; 00215 str << "lim::digits = " << lim::digits << ", lim::digits10 = " << lim::digits10 << endl; 00216 str << "lim::min_exponent = " << lim::min_exponent << ", lim::min_exponent10 = " << lim::min_exponent10 << endl; 00217 str << "lim::max_exponent = " << lim::max_exponent << ", lim::max_exponent10 = " << lim::max_exponent10 << endl; 00218 CPPUNIT_MESSAGE( str.str().c_str() ); 00219 */ 00220 00221 CHECK_COND(infinity == infinity); 00222 CHECK_COND(infinity > lim::max()); 00223 CHECK_COND(-infinity < -lim::max()); 00224 } 00225 00226 return true; 00227 } 00228 00229 //float generate_nan(float f) { 00230 // return 0.0f / f; 00231 //} 00232 template <class _Tp> 00233 bool test_qnan(const _Tp &) { 00234 typedef numeric_limits<_Tp> lim; 00235 if (lim::has_quiet_NaN) { 00236 const _Tp qnan = lim::quiet_NaN(); 00237 00238 //if (sizeof(_Tp) == 4) { 00239 // ostringstream str; 00240 // str << "qnan " << qnan << ", in hexa: " << showbase << hex << *((unsigned int*)&qnan); 00241 // CPPUNIT_MESSAGE( str.str().c_str() ); 00242 // str.str(""); 00243 // float val = generate_nan(0.0f); 00244 // str << "val " << val << ", in hexa: " << showbase << hex << *((unsigned int*)&val); 00245 // CPPUNIT_MESSAGE( str.str().c_str() ); 00246 // str.str(""); 00247 // val = -qnan; 00248 // str << "-qnan " << val << ", in hexa: " << showbase << hex << *((unsigned int*)&val); 00249 // CPPUNIT_MESSAGE( str.str().c_str() ); 00250 //} 00251 /* NaNs shall always compare "false" when compared for equality 00252 * If one of these fail, your compiler may be optimizing incorrectly, 00253 * or the STLport is incorrectly configured. 00254 */ 00255 CHECK_COND(! (qnan == 42)); 00256 CHECK_COND(! (qnan == qnan)); 00257 CHECK_COND(qnan != 42); 00258 CHECK_COND(qnan != qnan); 00259 00260 /* The following tests may cause arithmetic traps. 00261 * CHECK_COND(! (qnan < 42)); 00262 * CHECK_COND(! (qnan > 42)); 00263 * CHECK_COND(! (qnan <= 42)); 00264 * CHECK_COND(! (qnan >= 42)); 00265 */ 00266 } 00267 return true; 00268 } 00269 00270 00271 class ArbitraryType 00272 {}; 00273 00274 void LimitTest::test() { 00275 CPPUNIT_CHECK(test_integral_limits_base(bool())); 00276 CPPUNIT_CHECK(test_integral_limits(char())); 00277 typedef signed char signed_char; 00278 CPPUNIT_CHECK(test_signed_integral_limits(signed_char())); 00279 typedef unsigned char unsigned_char; 00280 CPPUNIT_CHECK(test_unsigned_integral_limits(unsigned_char())); 00281 # if defined (_STLP_HAS_WCHAR_T) && !defined (_STLP_WCHAR_T_IS_USHORT) 00282 CPPUNIT_CHECK(test_integral_limits(wchar_t())); 00283 # endif 00284 CPPUNIT_CHECK(test_signed_integral_limits(short())); 00285 typedef unsigned short unsigned_short; 00286 CPPUNIT_CHECK(test_unsigned_integral_limits(unsigned_short())); 00287 CPPUNIT_CHECK(test_signed_integral_limits(int())); 00288 typedef unsigned int unsigned_int; 00289 CPPUNIT_CHECK(test_unsigned_integral_limits(unsigned_int())); 00290 CPPUNIT_CHECK(test_signed_integral_limits(long())); 00291 typedef unsigned long unsigned_long; 00292 CPPUNIT_CHECK(test_unsigned_integral_limits(unsigned_long())); 00293 # if defined (_STLP_LONG_LONG) 00294 typedef _STLP_LONG_LONG long_long; 00295 CPPUNIT_CHECK(test_signed_integral_limits(long_long())); 00296 typedef unsigned _STLP_LONG_LONG unsigned_long_long; 00297 CPPUNIT_CHECK(test_unsigned_integral_limits(unsigned_long_long())); 00298 #endif 00299 00300 CPPUNIT_CHECK(test_float_limits(float())); 00301 CPPUNIT_CHECK(test_float_limits(double())); 00302 # if !defined ( _STLP_NO_LONG_DOUBLE ) 00303 typedef long double long_double; 00304 CPPUNIT_CHECK(test_float_limits(long_double())); 00305 # endif 00306 00307 CPPUNIT_ASSERT( !numeric_limits<ArbitraryType>::is_specialized ); 00308 } 00309 00310 void LimitTest::qnan_test() { 00311 CPPUNIT_CHECK(test_qnan(float())); 00312 CPPUNIT_CHECK(test_qnan(double())); 00313 # if !defined ( _STLP_NO_LONG_DOUBLE ) 00314 typedef long double long_double; 00315 CPPUNIT_CHECK(test_qnan(long_double())); 00316 # endif 00317 } Generated on Sun May 27 2012 04:35:28 for ReactOS by
1.7.6.1
|