lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
types.h
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