lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean built-in types (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_TYPES 00006 #define LEAN_TYPES 00007 00008 #include <cstddef> 00009 #include <climits> 00010 #include "cpp0x.h" 00011 00012 #ifdef DOXYGEN_READ_THIS 00013 00014 00015 #define LEAN_LONG_LONGER 00016 #undef LEAN_LONG_LONGER 00017 00018 00019 #define LEAN_INT_SHORTER 00020 #undef LEAN_INT_SHORTER 00021 #endif 00022 00023 namespace lean 00024 { 00025 00027 namespace types 00028 { 00029 00031 namespace sign_class 00032 { 00034 enum t 00035 { 00036 no_sign, 00037 sign 00038 }; 00039 } 00040 00042 template <sign_class::t Class, size_t Size> 00043 struct int_type 00044 { 00045 // Always checked, therefore use static_assert with care 00046 LEAN_STATIC_ASSERT_MSG_ALT(Size & ~Size, // = false, dependent 00047 "No integer type of the given size available.", 00048 No_integer_type_of_the_given_size_available); 00049 00051 typedef void type; 00052 }; 00053 00054 #ifndef DOXYGEN_SKIP_THIS 00055 00056 // Defaults that should work with most compilers 00057 template<> struct int_type<sign_class::sign, sizeof(char)> { typedef char type; }; 00058 #ifndef LEAN_INT_SHORTER 00059 template<> struct int_type<sign_class::sign, sizeof(short)> { typedef short type; }; 00060 #endif 00061 template<> struct int_type<sign_class::sign, sizeof(int)> { typedef int type; }; 00062 #ifdef LEAN_LONG_LONGER 00063 template<> struct int_type<sign_class::sign, sizeof(long)> { typedef long type; }; 00064 #endif 00065 template<> struct int_type<sign_class::sign, sizeof(long long)> { typedef long long type; }; 00066 00067 template<> struct int_type<sign_class::no_sign, sizeof(unsigned char)> { typedef unsigned char type; }; 00068 #ifndef LEAN_INT_SHORTER 00069 template<> struct int_type<sign_class::no_sign, sizeof(unsigned short)> { typedef unsigned short type; }; 00070 #endif 00071 template<> struct int_type<sign_class::no_sign, sizeof(unsigned int)> { typedef unsigned int type; }; 00072 #ifdef LEAN_LONG_LONGER 00073 template<> struct int_type<sign_class::sign, sizeof(unsigned long)> { typedef unsigned long type; }; 00074 #endif 00075 template<> struct int_type<sign_class::no_sign, sizeof(unsigned long long)> { typedef unsigned long long type; }; 00076 00077 #endif 00078 00079 // Count bytes rather than bits (number of bits per char undefined) 00080 00082 typedef int_type<sign_class::sign, 1>::type int1; 00084 typedef int_type<sign_class::sign, 2>::type int2; 00086 typedef int_type<sign_class::sign, 4>::type int4; 00088 typedef int_type<sign_class::sign, 8>::type int8; 00089 00091 typedef int_type<sign_class::no_sign, 1>::type uint1; 00093 typedef int_type<sign_class::no_sign, 2>::type uint2; 00095 typedef int_type<sign_class::no_sign, 4>::type uint4; 00097 typedef int_type<sign_class::no_sign, 8>::type uint8; 00098 00100 typedef int1 tristate; 00102 static const tristate caretrue = true; 00104 static const tristate carefalse = false; 00106 static const tristate dontcare = -1; 00107 00109 template <size_t Size> 00110 struct char_type 00111 { 00113 typedef typename int_type<sign_class::sign, Size>::type type; 00114 }; 00115 00116 #ifndef DOXYGEN_SKIP_THIS 00117 00118 // Defaults that should work with most compilers 00119 template<> struct char_type<sizeof(char)> { typedef char type; }; 00120 template<> struct char_type<sizeof(wchar_t)> { typedef wchar_t type; }; 00121 00122 #endif 00123 00125 typedef char_type<1>::type char1; 00127 typedef char_type<2>::type char2; 00129 typedef char_type<4>::type char4; 00130 00132 typedef char1 utf8_t; 00134 typedef char2 utf16_t; 00136 typedef char4 utf32_t; 00137 00139 template <size_t Size> 00140 struct float_type 00141 { 00142 // Always checked, therefore use static_assert with care 00143 LEAN_STATIC_ASSERT_MSG_ALT(Size & ~Size, // = false, dependent 00144 "No floating-point type of the given size available.", 00145 No_floating_point_type_of_the_given_size_available); 00146 00148 typedef void type; 00149 }; 00150 00151 #ifndef DOXYGEN_SKIP_THIS 00152 00153 // Defaults that should work with most compilers 00154 template<> struct float_type<sizeof(float)> { typedef float type; }; 00155 template<> struct float_type<sizeof(double)> { typedef double type; }; 00156 00157 #endif 00158 00160 typedef float_type<4>::type float4; 00162 typedef float_type<8>::type float8; 00163 00165 template <class Float> 00166 struct ieee_float_desc 00167 { 00168 // Always checked, therefore use static_assert with care 00169 LEAN_STATIC_ASSERT_MSG_ALT(!sizeof(Float), // = false, dependent 00170 "No utility methods available for the given floating-point type.", 00171 No_utility_methods_available_for_the_given_floating_point_type); 00172 00174 typedef Float float_type; 00176 typedef typename types::int_type<sign_class::no_sign, sizeof(Float)>::type int_type; 00178 typedef typename types::int_type<sign_class::sign, sizeof(Float)>::type shift_type; 00179 00181 static const size_t mantissa_bits; 00183 static const size_t exponent_bits; 00184 }; 00185 00186 #ifndef DOXYGEN_SKIP_THIS 00187 00188 template <> 00189 struct ieee_float_desc<float4> 00190 { 00191 typedef float4 float_type; 00192 typedef uint4 int_type; 00193 typedef int4 shift_type; 00194 00195 static const size_t mantissa_bits = 23; 00196 static const size_t exponent_bits = 8; 00197 static const shift_type exponent_bias = 127; 00198 }; 00199 00200 template <> 00201 struct ieee_float_desc<float8> 00202 { 00203 typedef float8 float_type; 00204 typedef uint8 int_type; 00205 typedef int4 shift_type; 00206 00207 static const size_t mantissa_bits = 52; 00208 static const size_t exponent_bits = 11; 00209 static const shift_type exponent_bias = 1023; 00210 }; 00211 00212 #endif 00213 00215 template < class Float, class Desc = ieee_float_desc<Float> > 00216 struct ieee_float : public Desc 00217 { 00219 typedef Desc desc_type; 00220 00221 typedef typename Desc::float_type float_type; 00222 typedef typename Desc::int_type int_type; 00223 typedef typename Desc::shift_type shift_type; 00224 00226 static const int_type mantissa_mask = (static_cast<int_type>(1) << mantissa_bits) - static_cast<int_type>(1); 00228 static const int_type exponent_mask = (static_cast<int_type>(1) << exponent_bits) - static_cast<int_type>(1); 00229 00231 static int_type mantissa(float_type value) 00232 { 00233 return reinterpret_cast<const int_type&>(value) & mantissa_mask; 00234 } 00236 static int_type exponent(float_type value) 00237 { 00238 return (reinterpret_cast<const int_type&>(value) >> mantissa_bits) & exponent_mask; 00239 } 00241 static int_type sign(float_type value) 00242 { 00243 return reinterpret_cast<const int_type&>(value) >> (exponent_bits + mantissa_bits); 00244 } 00245 00247 static shift_type shift(int_type exponent) 00248 { 00249 // Handle subnormal 00250 if (exponent == static_cast<int_type>(0)) 00251 exponent = 1; 00252 00253 return static_cast<shift_type>(exponent) - (exponent_bias + static_cast<shift_type>(mantissa_bits)); 00254 } 00256 static int_type fixed(int_type mantissa, int_type exponent) 00257 { 00258 // Add implicit one, if not subnormal 00259 if (exponent != static_cast<int_type>(0)) 00260 mantissa |= (static_cast<int_type>(1) << mantissa_bits); 00261 00262 return mantissa; 00263 } 00265 static bool is_special(int_type exponent) 00266 { 00267 return (exponent == exponent_mask); 00268 } 00270 static bool is_infinity(int_type mantissa) 00271 { 00272 return (mantissa == static_cast<int_type>(0)); 00273 } 00275 static bool is_nan(int_type mantissa) 00276 { 00277 return (mantissa != static_cast<int_type>(0)); 00278 } 00279 }; 00280 00282 using std::size_t; 00284 using std::ptrdiff_t; 00285 00286 #ifdef LEAN0X_NO_UINTPTR_T 00287 00288 typedef int_type<sign_class::no_sign, sizeof(void*)>::type uintptr_t; 00289 #else 00290 00291 using ::uintptr_t; 00292 #endif 00293 00295 static const size_t bits_per_byte = CHAR_BIT; 00296 00298 template <class Type> 00299 struct size_info 00300 { 00302 static const size_t bytes = sizeof(Type); 00304 static const size_t bits = bytes * bits_per_byte; 00305 }; 00306 00307 } 00308 00309 namespace sign_class = types::sign_class; 00310 using types::int_type; 00311 using types::float_type; 00312 using types::char_type; 00313 00314 using types::int1; 00315 using types::int2; 00316 using types::int4; 00317 using types::int8; 00318 00319 using types::uint1; 00320 using types::uint2; 00321 using types::uint4; 00322 using types::uint8; 00323 00324 using types::tristate; 00325 using types::caretrue; 00326 using types::carefalse; 00327 using types::dontcare; 00328 00329 using types::char1; 00330 using types::char2; 00331 using types::char4; 00332 00333 using types::utf8_t; 00334 using types::utf16_t; 00335 using types::utf32_t; 00336 00337 using types::float4; 00338 using types::float8; 00339 00340 using types::ieee_float_desc; 00341 using types::ieee_float; 00342 00343 using types::size_t; 00344 using types::ptrdiff_t; 00345 using types::uintptr_t; 00346 00347 using types::bits_per_byte; 00348 using types::size_info; 00349 00350 } 00351 00352 #endif