00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef PROMOTIONS_H_DEFINED
00039 #define PROMOTIONS_H_DEFINED
00040
00041 #include "Util/Types.H"
00042 #include "Util/log.H"
00043 #include <limits>
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 template <class T1, class T2>
00067 struct promote_trait { typedef T1 TP; enum { willPromote = 0 }; };
00068
00069
00070
00071
00072
00073 template <> struct promote_trait<byte, byte> { typedef int TP; enum { willPromote = 1 }; };
00074 template <> struct promote_trait<byte, int16> { typedef int TP; enum { willPromote = 1 }; };
00075 template <> struct promote_trait<byte, int32> { typedef int TP; enum { willPromote = 1 }; };
00076 template <> struct promote_trait<byte, float> { typedef float TP; enum { willPromote = 1 }; };
00077 template <> struct promote_trait<byte, double> { typedef double TP; enum { willPromote = 1 }; };
00078 template <> struct promote_trait<byte, long double> { typedef long double TP; enum { willPromote = 1 }; };
00079
00080 template <> struct promote_trait<int16, byte> { typedef int TP; enum { willPromote = 1 }; };
00081 template <> struct promote_trait<int16, int16> { typedef int TP; enum { willPromote = 1 }; };
00082 template <> struct promote_trait<int16, int32> { typedef int TP; enum { willPromote = 1 }; };
00083 template <> struct promote_trait<int16, float> { typedef float TP; enum { willPromote = 1 }; };
00084 template <> struct promote_trait<int16, double> { typedef double TP; enum { willPromote = 1 }; };
00085 template <> struct promote_trait<int16, long double> { typedef long double TP; enum { willPromote = 1 }; };
00086
00087 template <> struct promote_trait<int32, float> { typedef float TP; enum { willPromote = 1 }; };
00088 template <> struct promote_trait<int32, double> { typedef double TP; enum { willPromote = 1 }; };
00089 template <> struct promote_trait<int32, long double> { typedef long double TP; enum { willPromote = 1 }; };
00090
00091 template <> struct promote_trait<float, double> { typedef double TP; enum { willPromote = 1 }; };
00092 template <> struct promote_trait<float, long double> { typedef long double TP; enum { willPromote = 1 }; };
00093
00094 template <> struct promote_trait<double, long double> { typedef long double TP; enum { willPromote = 1 }; };
00095
00096
00097
00098 #define SPECIALIZE_PROMOTE_TRAIT(T_TYPE, T_PARAMS, T_ARGS) \
00099 template <T_PARAMS> class T_TYPE; \
00100 template <> struct promote_trait<T_TYPE<byte T_ARGS> , byte> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00101 template <> struct promote_trait<T_TYPE<byte T_ARGS> , int16> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00102 template <> struct promote_trait<T_TYPE<byte T_ARGS> , int32> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00103 template <> struct promote_trait<T_TYPE<byte T_ARGS> , float> { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00104 template <> struct promote_trait<T_TYPE<byte T_ARGS> , double> { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00105 template <> struct promote_trait<T_TYPE<byte T_ARGS> , long double> { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00106 \
00107 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , byte> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00108 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , int16> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00109 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , int32> { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00110 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , float> { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00111 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , double> { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00112 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , long double> { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00113 \
00114 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , float> { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00115 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , double> { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00116 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , long double> { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00117 \
00118 template <> struct promote_trait<T_TYPE<float T_ARGS> , double> { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00119 template <> struct promote_trait<T_TYPE<float T_ARGS> , long double> { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00120 \
00121 template <> struct promote_trait<T_TYPE<double T_ARGS> , long double> { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00122 \
00123 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<byte T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00124 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<int16 T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00125 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<int32 T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00126 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<float T_ARGS> > { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00127 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<double T_ARGS> > { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00128 template <> struct promote_trait<T_TYPE<byte T_ARGS> , T_TYPE<long double T_ARGS> > { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00129 \
00130 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<byte T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00131 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<int16 T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00132 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<int32 T_ARGS> > { typedef T_TYPE<int T_ARGS> TP; enum { willPromote = 1 }; }; \
00133 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<float T_ARGS> > { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00134 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<double T_ARGS> > { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00135 template <> struct promote_trait<T_TYPE<int16 T_ARGS> , T_TYPE<long double T_ARGS> > { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00136 \
00137 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , T_TYPE<float T_ARGS> > { typedef T_TYPE<float T_ARGS> TP; enum { willPromote = 1 }; }; \
00138 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , T_TYPE<double T_ARGS> > { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00139 template <> struct promote_trait<T_TYPE<int32 T_ARGS> , T_TYPE<long double T_ARGS> > { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00140 \
00141 template <> struct promote_trait<T_TYPE<float T_ARGS> , T_TYPE<double T_ARGS> > { typedef T_TYPE<double T_ARGS> TP; enum { willPromote = 1 }; }; \
00142 template <> struct promote_trait<T_TYPE<float T_ARGS> , T_TYPE<long double T_ARGS> > { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; }; \
00143 \
00144 template <> struct promote_trait<T_TYPE<double T_ARGS> , T_TYPE<long double T_ARGS> > { typedef T_TYPE<long double T_ARGS> TP; enum { willPromote = 1 }; };
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 template <class T1, class T2>
00171 struct promoteFromTo { enum { is_preserving = 1 }; };
00172
00173
00174 template <class T>
00175 struct promoteFromTo<T, T> { enum { is_preserving = 1 }; };
00176
00177
00178
00179
00180
00181 template <> struct promoteFromTo<int16 , byte> { enum { is_preserving = 0 }; };
00182 template <> struct promoteFromTo<int32 , byte> { enum { is_preserving = 0 }; };
00183 template <> struct promoteFromTo<float , byte> { enum { is_preserving = 0 }; };
00184 template <> struct promoteFromTo<double , byte> { enum { is_preserving = 0 }; };
00185 template <> struct promoteFromTo<long double, byte> { enum { is_preserving = 0 }; };
00186
00187 template <> struct promoteFromTo<int32 , int16> { enum { is_preserving = 0 }; };
00188 template <> struct promoteFromTo<float , int16> { enum { is_preserving = 0 }; };
00189 template <> struct promoteFromTo<double , int16> { enum { is_preserving = 0 }; };
00190 template <> struct promoteFromTo<long double, int16> { enum { is_preserving = 0 }; };
00191
00192 template <> struct promoteFromTo<float , int32> { enum { is_preserving = 0 }; };
00193 template <> struct promoteFromTo<double , int32> { enum { is_preserving = 0 }; };
00194 template <> struct promoteFromTo<long double, int32> { enum { is_preserving = 0 }; };
00195
00196 template <> struct promoteFromTo<double , float> { enum { is_preserving = 0 }; };
00197 template <> struct promoteFromTo<long double, float> { enum { is_preserving = 0 }; };
00198
00199 template <> struct promoteFromTo<long double, double> { enum { is_preserving = 0 }; };
00200
00201
00202
00203
00204
00205
00206
00207
00208 template <class dst_type, class src_type,
00209 bool need_rounding =
00210 (std::numeric_limits<dst_type>::is_integer
00211 && !std::numeric_limits<src_type>::is_integer)>
00212 struct round_helper;
00213
00214 template <class dst_type, class src_type>
00215 struct round_helper<dst_type, src_type, false>
00216 {
00217 inline static dst_type round(src_type x)
00218 { return dst_type(x); }
00219 };
00220
00221 template <class dst_type, class src_type>
00222 struct round_helper<dst_type, src_type, true>
00223 {
00224 inline static dst_type round(src_type x)
00225 {
00226 if (x > 0) return dst_type(x+0.5);
00227 else if (x < 0) return dst_type(x-0.5);
00228 else return dst_type(0);
00229 }
00230 };
00231
00232
00233
00234
00235
00236
00237
00238
00239 template <class dst_type, class src_type,
00240 bool is_preserving =
00241 promoteFromTo<src_type, dst_type>::is_preserving,
00242 bool dst_type_is_integer =
00243 std::numeric_limits<dst_type>::is_integer>
00244 struct convert_helper;
00245
00246
00247 template <class dst_type, class src_type>
00248 struct convert_helper<dst_type, src_type,
00249 false,
00250 true>
00251 {
00252 inline static dst_type convert(src_type x)
00253 {
00254 if (x < std::numeric_limits<dst_type>::min())
00255 return std::numeric_limits<dst_type>::min();
00256 if (x > std::numeric_limits<dst_type>::max())
00257 return std::numeric_limits<dst_type>::max();
00258 return dst_type(x);
00259 }
00260
00261 inline static dst_type rounded_convert(src_type x)
00262 {
00263 if (x < std::numeric_limits<dst_type>::min())
00264 return std::numeric_limits<dst_type>::min();
00265 if (x > std::numeric_limits<dst_type>::max())
00266 return std::numeric_limits<dst_type>::max();
00267
00268 return round_helper<dst_type, src_type>::round(x);
00269 }
00270 };
00271
00272
00273 template <class dst_type, class src_type>
00274 struct convert_helper<dst_type, src_type,
00275 false,
00276 false>
00277 {
00278 inline static dst_type convert(src_type x)
00279 {
00280 if (x < -std::numeric_limits<dst_type>::max())
00281 return -std::numeric_limits<dst_type>::max();
00282 if (x > std::numeric_limits<dst_type>::max())
00283 return std::numeric_limits<dst_type>::max();
00284 return dst_type(x);
00285 }
00286
00287 inline static dst_type rounded_convert(src_type x)
00288 {
00289 if (x < -std::numeric_limits<dst_type>::max())
00290 return -std::numeric_limits<dst_type>::max();
00291 if (x > std::numeric_limits<dst_type>::max())
00292 return std::numeric_limits<dst_type>::max();
00293
00294 return round_helper<dst_type, src_type>::round(x);
00295 }
00296 };
00297
00298
00299
00300
00301
00302
00303 template <class dst_type, class src_type>
00304 struct convert_helper<dst_type, src_type,
00305 true,
00306 true>
00307 {
00308 inline static dst_type convert(src_type x)
00309 {
00310 return dst_type(x);
00311 }
00312
00313 inline static dst_type rounded_convert(src_type x)
00314 {
00315 return round_helper<dst_type, src_type>::round(x);
00316 }
00317 };
00318
00319 template <class dst_type, class src_type>
00320 struct convert_helper<dst_type, src_type,
00321 true,
00322 false>
00323 {
00324 inline static dst_type convert(src_type x)
00325 {
00326 return dst_type(x);
00327 }
00328
00329 inline static dst_type rounded_convert(src_type x)
00330 {
00331 return round_helper<dst_type, src_type>::round(x);
00332 }
00333 };
00334
00335
00336 template <class dst_type, class src_type>
00337 inline
00338 dst_type clamped_convert(src_type x)
00339 {
00340 return convert_helper<dst_type, src_type>::convert(x);
00341 }
00342
00343
00344 template <class dst_type, class src_type>
00345 inline
00346 dst_type clamped_rounded_convert(src_type x)
00347 {
00348 return convert_helper<dst_type, src_type>::rounded_convert(x);
00349 }
00350
00351 #endif
00352
00353
00354
00355
00356
00357