00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef TVMET_TYPE_PROMOTION_H
00025 #define TVMET_TYPE_PROMOTION_H
00026
00027 namespace tvmet {
00028
00029
00041 template<class T>
00042 struct PrecisionTraits {
00043 enum {
00044 rank = 0,
00045 known = 0
00046 };
00047 };
00048
00049
00050 #define TVMET_PRECISION(T,R) \
00051 template<> \
00052 struct PrecisionTraits< T > { \
00053 enum { \
00054 rank = R, \
00055 known = 1 \
00056 }; \
00057 };
00058
00059
00060
00061
00062
00063 TVMET_PRECISION(int, 100)
00064 TVMET_PRECISION(unsigned int, 200)
00065 TVMET_PRECISION(long, 300)
00066 TVMET_PRECISION(unsigned long, 400)
00067
00068 #if defined(TVMET_HAVE_LONG_LONG)
00069 TVMET_PRECISION(long long, 500)
00070 TVMET_PRECISION(unsigned long long, 600)
00071 #endif // defined(TVMET_HAVE_LONG_LONG)
00072
00073 TVMET_PRECISION(float, 700)
00074 TVMET_PRECISION(double, 800)
00075
00076 #if defined(TVMET_HAVE_LONG_DOUBLE)
00077 TVMET_PRECISION(long double, 900)
00078 #endif // defined(TVMET_HAVE_LONG_DOUBLE)
00079
00080
00081
00082
00083
00084 #if defined(TVMET_HAVE_COMPLEX)
00085 TVMET_PRECISION(std::complex<int>, 1000)
00086 TVMET_PRECISION(std::complex<unsigned int>, 1100)
00087 TVMET_PRECISION(std::complex<long>, 1200)
00088 TVMET_PRECISION(std::complex<unsigned long>, 1300)
00089
00090 #if defined(TVMET_HAVE_LONG_LONG)
00091 TVMET_PRECISION(std::complex<long long>, 1400)
00092 TVMET_PRECISION(std::complex<unsigned long long>, 1500)
00093 #endif // defined(TVMET_HAVE_LONG_LONG)
00094
00095 TVMET_PRECISION(std::complex<float>, 1600)
00096 TVMET_PRECISION(std::complex<double>, 1700)
00097
00098 #if defined(TVMET_HAVE_LONG_DOUBLE)
00099 TVMET_PRECISION(std::complex<long double>, 1800)
00100 #endif // defined(TVMET_HAVE_LONG_DOUBLE)
00101
00102 #endif // defined(TVMET_HAVE_COMPLEX)
00103
00104
00124 #undef TVMET_PRECISION
00125
00126
00131 template<class T>
00132 struct AutopromoteTraits {
00133 typedef T value_type;
00134 };
00135
00136
00137
00138
00139
00140
00141
00142 #define TVMET_AUTOPROMOTE(T1,T2) \
00143 template<> \
00144 struct AutopromoteTraits<T1> { \
00145 typedef T2 value_type; \
00146 };
00147
00148 TVMET_AUTOPROMOTE(bool, int)
00149 TVMET_AUTOPROMOTE(char, int)
00150 TVMET_AUTOPROMOTE(unsigned char, int)
00151 TVMET_AUTOPROMOTE(short int, int)
00152 TVMET_AUTOPROMOTE(short unsigned int, unsigned int)
00153
00160 #undef TVMET_AUTOPROMOTE
00161
00162
00167 template<class T1, class T2, int promoteToT1>
00168 struct promoteTo {
00169 typedef T1 value_type;
00170 };
00171
00172
00177 template<class T1, class T2>
00178 struct promoteTo<T1,T2,0> {
00179 typedef T2 value_type;
00180 };
00181
00182
00187 template<class T1org, class T2org>
00188 class PromoteTraits {
00189
00190 typedef typename AutopromoteTraits<T1org>::value_type T1;
00191 typedef typename AutopromoteTraits<T2org>::value_type T2;
00192
00193 enum {
00194
00195 T1IsBetter = int(PrecisionTraits<T1>::rank) > int(PrecisionTraits<T2>::rank),
00196
00197
00198 knowBothRanks = PrecisionTraits<T1>::known && PrecisionTraits<T2>::known,
00199
00200
00201 knowT1butNotT2 = PrecisionTraits<T1>::known && !(PrecisionTraits<T2>::known),
00202
00203
00204 knowT2butNotT1 = PrecisionTraits<T2>::known && !(PrecisionTraits<T1>::known),
00205
00206
00207 T1IsLarger = sizeof(T1) >= sizeof(T2),
00208
00209
00210
00211
00212 defaultPromotion = knowT1butNotT2 ? false : (knowT2butNotT1 ? true : T1IsLarger),
00213
00214
00215
00216
00217 promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion) ? 1 : 0
00218 };
00219
00220 public:
00221 typedef typename promoteTo<T1,T2,promoteToT1>::value_type value_type;
00222 };
00223
00224
00225 }
00226
00227 #endif // TVMET_TYPE_PROMOTION_H
00228
00229
00230
00231
00232